added support for account sorting

This commit is contained in:
John Wiegley 2004-08-05 21:47:53 -04:00
parent 7e87a0a0b1
commit 50f75e0a5c
5 changed files with 124 additions and 130 deletions

View file

@ -34,12 +34,14 @@ class account_t;
class transaction_t class transaction_t
{ {
public: public:
entry_t * entry; entry_t * entry;
account_t * account; account_t * account;
amount_t amount; amount_t amount;
amount_t cost; amount_t cost;
unsigned int flags; unsigned int flags;
std::string note; std::string note;
balance_pair_t total;
unsigned int index;
transaction_t(entry_t * _entry, account_t * _account) transaction_t(entry_t * _entry, account_t * _account)
: entry(_entry), account(_account), flags(TRANSACTION_NORMAL) {} : entry(_entry), account(_account), flags(TRANSACTION_NORMAL) {}

View file

@ -822,7 +822,7 @@ int main(int argc, char * argv[])
format_t format(f); format_t format(f);
walk_accounts(journal->master, format_account(std::cout, format), walk_accounts(journal->master, format_account(std::cout, format),
predicate.get(), show_related, show_inverted, predicate.get(), show_related, show_inverted,
show_subtotals, display_predicate.get()); show_subtotals, display_predicate.get(), sort_order.get());
if (! display_predicate.get() || if (! display_predicate.get() ||
item_predicate(display_predicate.get())(journal->master)) { item_predicate(display_predicate.get())(journal->master)) {
@ -856,7 +856,7 @@ int main(int argc, char * argv[])
collect_transactions(transactions_pool), predicate.get(), collect_transactions(transactions_pool), predicate.get(),
show_related, show_inverted, display_predicate.get()); show_related, show_inverted, display_predicate.get());
std::stable_sort(transactions_pool.begin(), transactions_pool.end(), std::stable_sort(transactions_pool.begin(), transactions_pool.end(),
compare_transactions(sort_order.get())); compare_items<transaction_t>(sort_order.get()));
walk_transactions(transactions_pool.begin(), transactions_pool.end(), walk_transactions(transactions_pool.begin(), transactions_pool.end(),
formatter, NULL, show_related, show_inverted, formatter, NULL, show_related, show_inverted,
display_predicate.get()); display_predicate.get());

View file

@ -116,34 +116,36 @@ void node_t::compute(balance_t& result, const details_t& details) const
break; break;
case BALANCE: case BALANCE:
if (details.balance) { if (details.xact) {
result = details.balance->quantity; result = details.xact->total.quantity;
if (details.xact) result -= details.xact->amount;
result -= details.xact->amount; }
else if (details.account) else if (details.account) {
result -= details.account->value.quantity; result = details.account->total.quantity;
result -= details.account->value.quantity;
} }
break; break;
case COST_BALANCE: case COST_BALANCE:
if (details.balance) { if (details.xact) {
result = details.balance->cost; result = details.xact->total.cost;
if (details.xact) result -= details.xact->cost;
result -= details.xact->cost; }
else if (details.account) else if (details.account) {
result -= details.account->value.cost; result = details.account->total.cost;
result -= details.account->value.cost;
} }
break; break;
case TOTAL: case TOTAL:
if (details.balance) if (details.xact)
result = details.balance->quantity; result = details.xact->total.quantity;
else if (details.account) else if (details.account)
result = details.account->total.quantity; result = details.account->total.quantity;
break; break;
case COST_TOTAL: case COST_TOTAL:
if (details.balance) if (details.xact)
result = details.balance->cost; result = details.xact->total.cost;
else if (details.account) else if (details.account)
result = details.account->total.cost; result = details.account->total.cost;
break; break;
@ -164,15 +166,15 @@ void node_t::compute(balance_t& result, const details_t& details) const
break; break;
case INDEX: case INDEX:
if (details.index) if (details.xact)
result = *details.index + 1; result = details.xact->index + 1;
break; break;
case F_ARITH_MEAN: case F_ARITH_MEAN:
if (details.index) { if (details.xact) {
assert(left); assert(left);
left->compute(result, details); left->compute(result, details);
result /= amount_t(*details.index + 1); result /= amount_t(details.xact->index + 1);
} }
break; break;

View file

@ -33,26 +33,17 @@ struct details_t
const entry_t * entry; const entry_t * entry;
const transaction_t * xact; const transaction_t * xact;
const account_t * account; const account_t * account;
const balance_pair_t * balance;
const unsigned int * index;
const unsigned int depth; const unsigned int depth;
details_t(const entry_t * _entry, details_t(const entry_t * _entry)
const balance_pair_t * _balance = NULL, : entry(_entry), xact(NULL), account(NULL), depth(0) {}
const unsigned int * _index = NULL)
: entry(_entry), xact(NULL), account(NULL),
balance(_balance), index(_index), depth(0) {}
details_t(const transaction_t * _xact, details_t(const transaction_t * _xact)
const balance_pair_t * _balance = NULL, : entry(_xact->entry), xact(_xact), account(_xact->account), depth(0) {}
const unsigned int * _index = NULL)
: entry(_xact->entry), xact(_xact), account(_xact->account),
balance(_balance), index(_index), depth(0) {}
details_t(const account_t * _account, details_t(const account_t * _account,
const unsigned int _depth = 0) const unsigned int _depth = 0)
: entry(NULL), xact(NULL), account(_account), : entry(NULL), xact(NULL), account(_account), depth(_depth) {}
balance(NULL), index(NULL), depth(_depth) {}
}; };
struct node_t struct node_t

175
walk.h
View file

@ -14,19 +14,14 @@ namespace ledger {
class item_predicate class item_predicate
{ {
const node_t * predicate; const node_t * predicate;
balance_pair_t * balance;
unsigned int * index;
public: public:
item_predicate(const node_t * _predicate, item_predicate(const node_t * _predicate) : predicate(_predicate) {}
balance_pair_t * _balance = NULL,
unsigned int * _index = NULL)
: predicate(_predicate), balance(_balance), index(_index) {}
bool operator()(const entry_t * entry) const { bool operator()(const entry_t * entry) const {
if (predicate) { if (predicate) {
balance_t result; balance_t result;
predicate->compute(result, details_t(entry, balance, index)); predicate->compute(result, details_t(entry));
return result; return result;
} else { } else {
return true; return true;
@ -36,7 +31,7 @@ class item_predicate
bool operator()(const transaction_t * xact) const { bool operator()(const transaction_t * xact) const {
if (predicate) { if (predicate) {
balance_t result; balance_t result;
predicate->compute(result, details_t(xact, balance, index)); predicate->compute(result, details_t(xact));
return result; return result;
} else { } else {
return true; return true;
@ -68,10 +63,11 @@ inline void add_to_balance_pair(balance_pair_t& balance,
class format_transaction class format_transaction
{ {
std::ostream& output_stream; std::ostream& output_stream;
const format_t& first_line_format; const format_t& first_line_format;
const format_t& next_lines_format; const format_t& next_lines_format;
mutable entry_t * last_entry; unsigned int index;
entry_t * last_entry;
public: public:
format_transaction(std::ostream& _output_stream, format_transaction(std::ostream& _output_stream,
@ -80,24 +76,21 @@ class format_transaction
: output_stream(_output_stream), : output_stream(_output_stream),
first_line_format(_first_line_format), first_line_format(_first_line_format),
next_lines_format(_next_lines_format), next_lines_format(_next_lines_format),
last_entry(NULL) {} index(0), last_entry(NULL) {}
void operator()(transaction_t * xact, void operator()(transaction_t * xact, const bool inverted);
balance_pair_t * balance,
unsigned int * index,
const bool inverted) const;
}; };
struct compare_transactions { template <typename T>
struct compare_items {
const node_t * sort_order; const node_t * sort_order;
compare_transactions(const node_t * _sort_order) compare_items(const node_t * _sort_order)
: sort_order(_sort_order) { : sort_order(_sort_order) {
assert(sort_order); assert(sort_order);
} }
bool operator()(const transaction_t * left, bool operator()(const T * left, const T * right) const {
const transaction_t * right) const {
assert(left); assert(left);
assert(right); assert(right);
balance_t left_result; balance_t left_result;
@ -118,21 +111,22 @@ class collect_transactions
collect_transactions(transactions_deque& _transactions) collect_transactions(transactions_deque& _transactions)
: transactions(_transactions) {} : transactions(_transactions) {}
void operator()(transaction_t * xact, void operator()(transaction_t * xact, const bool inverted) {
balance_pair_t * balance,
unsigned int * index,
const bool inverted) {
transactions.push_back(xact); transactions.push_back(xact);
} }
}; };
inline void sort_transactions(transactions_deque& transactions,
const node_t * sort_order)
{
std::stable_sort(transactions.begin(), transactions.end(),
compare_items<transaction_t>(sort_order));
}
class ignore_transaction class ignore_transaction
{ {
public: public:
void operator()(transaction_t * xact, void operator()(transaction_t * xact, const bool inverted) const {}
balance_pair_t * balance,
unsigned int * index,
const bool inverted) const {}
}; };
template <typename Function> template <typename Function>
@ -140,16 +134,14 @@ void handle_transaction(transaction_t * xact,
Function functor, Function functor,
item_predicate& pred_functor, item_predicate& pred_functor,
const bool related, const bool related,
const bool inverted, const bool inverted)
balance_pair_t * balance = NULL,
unsigned int * index = NULL)
{ {
// If inverted is true, it implies related. // If inverted is true, it implies related.
if (! inverted && ! (xact->flags & TRANSACTION_HANDLED)) { if (! inverted && ! (xact->flags & TRANSACTION_HANDLED)) {
xact->flags |= TRANSACTION_HANDLED; xact->flags |= TRANSACTION_HANDLED;
if (pred_functor(xact)) { if (pred_functor(xact)) {
xact->flags |= TRANSACTION_DISPLAYED; xact->flags |= TRANSACTION_DISPLAYED;
functor(xact, balance, index, inverted); functor(xact, inverted);
} }
} }
@ -164,7 +156,7 @@ void handle_transaction(transaction_t * xact,
(*i)->flags |= TRANSACTION_HANDLED; (*i)->flags |= TRANSACTION_HANDLED;
if (pred_functor(xact)) { if (pred_functor(xact)) {
xact->flags |= TRANSACTION_DISPLAYED; xact->flags |= TRANSACTION_DISPLAYED;
functor(*i, balance, index, inverted); functor(*i, inverted);
} }
} }
} }
@ -178,18 +170,15 @@ void walk_entries(entries_list::iterator begin,
const bool inverted, const bool inverted,
const node_t * display_predicate = NULL) const node_t * display_predicate = NULL)
{ {
balance_pair_t balance; item_predicate pred_functor(predicate);
unsigned int index; item_predicate disp_pred_functor(display_predicate);
item_predicate pred_functor(predicate, &balance, &index);
item_predicate disp_pred_functor(display_predicate, &balance, &index);
for (entries_list::iterator i = begin; i != end; i++) for (entries_list::iterator i = begin; i != end; i++)
for (transactions_list::iterator j = (*i)->transactions.begin(); for (transactions_list::iterator j = (*i)->transactions.begin();
j != (*i)->transactions.end(); j != (*i)->transactions.end();
j++) j++)
if (pred_functor(*j)) if (pred_functor(*j))
handle_transaction(*j, functor, disp_pred_functor, handle_transaction(*j, functor, disp_pred_functor, related, inverted);
related, inverted, &balance, &index);
} }
template <typename Function> template <typename Function>
@ -201,11 +190,8 @@ void walk_transactions(transactions_list::iterator begin,
const bool inverted, const bool inverted,
const node_t * display_predicate = NULL) const node_t * display_predicate = NULL)
{ {
balance_pair_t balance;
unsigned int index;
for (transactions_list::iterator i = begin; i != end; i++) for (transactions_list::iterator i = begin; i != end; i++)
functor(*i, &balance, &index, inverted); functor(*i, inverted);
} }
template <typename Function> template <typename Function>
@ -217,19 +203,15 @@ void walk_transactions(transactions_deque::iterator begin,
const bool inverted, const bool inverted,
const node_t * display_predicate = NULL) const node_t * display_predicate = NULL)
{ {
balance_pair_t balance;
unsigned int index;
for (transactions_deque::iterator i = begin; i != end; i++) for (transactions_deque::iterator i = begin; i != end; i++)
functor(*i, &balance, &index, inverted); functor(*i, inverted);
} }
class format_account class format_account
{ {
std::ostream& output_stream; std::ostream& output_stream;
const format_t& format; const format_t& format;
const account_t * last_account;
mutable const account_t * last_account;
public: public:
format_account(std::ostream& _output_stream, const format_t& _format) format_account(std::ostream& _output_stream, const format_t& _format)
@ -238,11 +220,20 @@ class format_account
void operator()(const account_t * account, bool report_top = false); void operator()(const account_t * account, bool report_top = false);
}; };
void calc__accounts(account_t * account, typedef std::deque<account_t *> accounts_deque;
const node_t * predicate,
const bool related, inline void sort_accounts(account_t * account,
const bool inverted, accounts_deque& accounts,
const bool calc_subtotals); const node_t * sort_order)
{
for (accounts_map::iterator i = account->accounts.begin();
i != account->accounts.end();
i++)
accounts.push_back((*i).second);
std::stable_sort(accounts.begin(), accounts.end(),
compare_items<account_t>(sort_order));
}
template <typename Function> template <typename Function>
void walk__accounts(const account_t * account, void walk__accounts(const account_t * account,
@ -258,6 +249,37 @@ void walk__accounts(const account_t * account,
walk__accounts((*i).second, functor, display_predicate); walk__accounts((*i).second, functor, display_predicate);
} }
template <typename Function>
void walk__accounts_sorted(const account_t * account,
Function functor,
const node_t * sort_order,
const node_t * display_predicate)
{
if (! display_predicate || item_predicate(display_predicate)(account))
functor(account);
accounts_deque accounts;
for (accounts_map::const_iterator i = account->accounts.begin();
i != account->accounts.end();
i++)
accounts.push_back((*i).second);
std::stable_sort(accounts.begin(), accounts.end(),
compare_items<account_t>(sort_order));
for (accounts_deque::const_iterator i = accounts.begin();
i != accounts.end();
i++)
walk__accounts_sorted(*i, functor, sort_order, display_predicate);
}
void calc__accounts(account_t * account,
const node_t * predicate,
const bool related,
const bool inverted,
const bool calc_subtotals);
template <typename Function> template <typename Function>
void walk_accounts(account_t * account, void walk_accounts(account_t * account,
Function functor, Function functor,
@ -265,41 +287,18 @@ void walk_accounts(account_t * account,
const bool related, const bool related,
const bool inverted, const bool inverted,
const bool calc_subtotals, const bool calc_subtotals,
const node_t * display_predicate = NULL) const node_t * display_predicate = NULL,
const node_t * sort_order = NULL)
{ {
calc__accounts(account, predicate, related, inverted, calc_subtotals); calc__accounts(account, predicate, related, inverted, calc_subtotals);
walk__accounts<Function>(account, functor, display_predicate);
if (sort_order)
walk__accounts_sorted<Function>(account, functor, sort_order,
display_predicate);
else
walk__accounts<Function>(account, functor, display_predicate);
} }
#if 0
void sum_entries(entries_list& entries,
account_t * account,
const bool show_subtotals)
{
for (entries_list::const_iterator i = entries.begin();
i != entries.end();
i++)
for (transactions_list::const_iterator j = (*i)->transactions.begin();
j != (*i)->transactions.end();
j++)
if ((*j)->account == account) {
account->value += *(*j);
if (show_subtotals)
for (account_t * a = account;
a;
a = a->parent)
a->total += *(*j);
}
for (accounts_map::iterator i = account->accounts.begin();
i != account->accounts.end();
i++)
sum_items(entries, *i, show_subtotals);
}
#endif
} // namespace ledger } // namespace ledger
#endif // _WALK_H #endif // _WALK_H