added support for account sorting
This commit is contained in:
parent
7e87a0a0b1
commit
50f75e0a5c
5 changed files with 124 additions and 130 deletions
14
ledger.h
14
ledger.h
|
|
@ -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) {}
|
||||||
|
|
|
||||||
4
main.cc
4
main.cc
|
|
@ -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());
|
||||||
|
|
|
||||||
42
valexpr.cc
42
valexpr.cc
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
19
valexpr.h
19
valexpr.h
|
|
@ -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
175
walk.h
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue