fixed account display bug
This commit is contained in:
parent
2dc822291f
commit
05b2cc46fd
7 changed files with 140 additions and 86 deletions
79
format.cc
79
format.cc
|
|
@ -397,44 +397,59 @@ void format_transaction::operator()(transaction_t * xact) const
|
||||||
last_xact = xact;
|
last_xact = xact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool format_account::disp_subaccounts_p(const account_t * account,
|
||||||
void format_account::operator()(account_t * account,
|
const item_predicate<account_t>&
|
||||||
const unsigned int max_depth,
|
disp_pred_functor,
|
||||||
const bool report_top) const
|
const account_t *& to_show)
|
||||||
{
|
{
|
||||||
// Don't output the account if only one child will be displayed
|
bool display = false;
|
||||||
// which shows the exact same amount. jww (2004-08-03): How do
|
unsigned int counted = 0;
|
||||||
// compute the right figure? It should a value expression specified
|
|
||||||
// by the user, to say, "If this expression is equivalent between a
|
|
||||||
// parent account and a lone displayed child, then don't display the
|
|
||||||
// parent."
|
|
||||||
|
|
||||||
if (bool output = ((report_top || account->parent != NULL) &&
|
to_show = NULL;
|
||||||
disp_pred_functor(account))) {
|
|
||||||
int counted = 0;
|
|
||||||
bool display = false;
|
|
||||||
|
|
||||||
for (accounts_map::const_iterator i = account->accounts.begin();
|
for (accounts_map::const_iterator i = account->accounts.begin();
|
||||||
i != account->accounts.end();
|
i != account->accounts.end();
|
||||||
i++) {
|
i++) {
|
||||||
if (! (*i).second->total)
|
// jww (2004-08-03): How do compute the right figure? It should a
|
||||||
continue;
|
// value expression specified by the user, to say, "If this
|
||||||
|
// expression is equivalent between a parent account and a lone
|
||||||
|
// displayed child, then don't display the parent."
|
||||||
|
|
||||||
if ((*i).second->total != account->total || counted > 0) {
|
if (! (*i).second->total || ! disp_pred_functor((*i).second))
|
||||||
display = true;
|
continue;
|
||||||
break;
|
|
||||||
}
|
if ((*i).second->total != account->total || counted > 0) {
|
||||||
counted++;
|
display = true;
|
||||||
}
|
break;
|
||||||
|
|
||||||
if (counted == 1 && ! display)
|
|
||||||
output = false;
|
|
||||||
|
|
||||||
if (output && (max_depth == 0 || account->depth <= max_depth)) {
|
|
||||||
format.format_elements(output_stream, details_t(account));
|
|
||||||
account->dflags |= ACCOUNT_DISPLAYED;
|
|
||||||
}
|
}
|
||||||
|
to_show = (*i).second;
|
||||||
|
counted++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool format_account::display_account(const account_t * account,
|
||||||
|
const item_predicate<account_t>&
|
||||||
|
disp_pred_functor)
|
||||||
|
{
|
||||||
|
// Never display the master account, or an account that has already
|
||||||
|
// been displayed.
|
||||||
|
if (! account->parent || account->dflags & ACCOUNT_DISPLAYED)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// At this point, one of two possibilities exists: the account is a
|
||||||
|
// leaf which matches the predicate restrictions; or it is a parent
|
||||||
|
// and two or more children must be subtotaled; or it is a parent
|
||||||
|
// and its child has been hidden by the predicate. So first,
|
||||||
|
// determine if it is a parent that must be displayed regardless of
|
||||||
|
// the predicate.
|
||||||
|
|
||||||
|
const account_t * account_to_show = NULL;
|
||||||
|
if (disp_subaccounts_p(account, disp_pred_functor, account_to_show))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return ! account_to_show && disp_pred_functor(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
24
format.h
24
format.h
|
|
@ -204,9 +204,20 @@ class format_account
|
||||||
: output_stream(_output_stream), format(_format),
|
: output_stream(_output_stream), format(_format),
|
||||||
disp_pred_functor(display_predicate) {}
|
disp_pred_functor(display_predicate) {}
|
||||||
|
|
||||||
void operator()(account_t * account,
|
static bool disp_subaccounts_p(const account_t * account,
|
||||||
const unsigned int max_depth = 1,
|
const item_predicate<account_t>&
|
||||||
const bool report_top = false) const;
|
disp_pred_functor,
|
||||||
|
const account_t *& to_show);
|
||||||
|
static bool display_account(const account_t * account,
|
||||||
|
const item_predicate<account_t>&
|
||||||
|
disp_pred_functor);
|
||||||
|
|
||||||
|
void operator()(const account_t * account) const {
|
||||||
|
if (display_account(account, disp_pred_functor)) {
|
||||||
|
format.format_elements(output_stream, details_t(account));
|
||||||
|
account->dflags |= ACCOUNT_DISPLAYED;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -241,11 +252,8 @@ class format_equity
|
||||||
next_lines_format.format_elements(output_stream, details_t(&summary));
|
next_lines_format.format_elements(output_stream, details_t(&summary));
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(account_t * account,
|
void operator()(const account_t * account) const {
|
||||||
const unsigned int max_depth = 1,
|
if (format_account::display_account(account, disp_pred_functor)) {
|
||||||
const bool report_top = false) const {
|
|
||||||
if ((report_top || account->parent != NULL) &&
|
|
||||||
disp_pred_functor(account)) {
|
|
||||||
next_lines_format.format_elements(output_stream, details_t(account));
|
next_lines_format.format_elements(output_stream, details_t(account));
|
||||||
account->dflags |= ACCOUNT_DISPLAYED;
|
account->dflags |= ACCOUNT_DISPLAYED;
|
||||||
total += account->value.quantity;
|
total += account->value.quantity;
|
||||||
|
|
|
||||||
20
ledger.h
20
ledger.h
|
|
@ -41,9 +41,10 @@ class transaction_t
|
||||||
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;
|
mutable balance_pair_t total;
|
||||||
unsigned int dflags;
|
mutable unsigned int index;
|
||||||
|
mutable unsigned int dflags;
|
||||||
|
|
||||||
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),
|
||||||
|
|
@ -105,15 +106,16 @@ class account_t
|
||||||
account_t * parent;
|
account_t * parent;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string note;
|
std::string note;
|
||||||
unsigned long depth;
|
unsigned int depth;
|
||||||
accounts_map accounts;
|
accounts_map accounts;
|
||||||
transactions_list transactions;
|
transactions_list transactions;
|
||||||
balance_pair_t value;
|
|
||||||
balance_pair_t total;
|
|
||||||
unsigned long ident;
|
|
||||||
unsigned long dflags;
|
|
||||||
|
|
||||||
mutable std::string _fullname;
|
mutable balance_pair_t value;
|
||||||
|
mutable balance_pair_t total;
|
||||||
|
mutable unsigned long ident;
|
||||||
|
mutable unsigned long dflags;
|
||||||
|
mutable std::string _fullname;
|
||||||
|
|
||||||
static unsigned long next_ident;
|
static unsigned long next_ident;
|
||||||
|
|
||||||
account_t(account_t * _parent,
|
account_t(account_t * _parent,
|
||||||
|
|
|
||||||
31
main.cc
31
main.cc
|
|
@ -570,10 +570,19 @@ int main(int argc, char * argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (display_predicate_string.empty()) {
|
if (display_predicate_string.empty()) {
|
||||||
if (command == "b" && ! show_empty)
|
if (command == "b") {
|
||||||
display_predicate_string = "T";
|
if (! show_empty)
|
||||||
else if (command == "E")
|
display_predicate_string = "T";
|
||||||
|
|
||||||
|
if (! show_expanded) {
|
||||||
|
if (! display_predicate_string.empty())
|
||||||
|
display_predicate_string += "&";
|
||||||
|
display_predicate_string += "!n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (command == "E") {
|
||||||
display_predicate_string = "a";
|
display_predicate_string = "a";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! display_predicate_string.empty()) {
|
if (! display_predicate_string.empty()) {
|
||||||
|
|
@ -640,16 +649,12 @@ int main(int argc, char * argv[])
|
||||||
format_t format(first_line_format);
|
format_t format(first_line_format);
|
||||||
format_account formatter(std::cout, format, display_predicate.get());
|
format_account formatter(std::cout, format, display_predicate.get());
|
||||||
walk_accounts(journal->master, formatter, predicate.get(),
|
walk_accounts(journal->master, formatter, predicate.get(),
|
||||||
xact_display_flags, show_subtotals, show_expanded ? 0 : 1,
|
xact_display_flags, show_subtotals, sort_order.get());
|
||||||
sort_order.get());
|
|
||||||
|
|
||||||
if (! display_predicate.get() ||
|
std::string end_format = "--------------------\n";
|
||||||
item_predicate<account_t>(display_predicate.get())(journal->master)) {
|
format.reset(end_format + f);
|
||||||
std::string end_format = "--------------------\n";
|
format_account(std::cout, format,
|
||||||
format.reset(end_format + f);
|
display_predicate.get())(journal->master);
|
||||||
format_account(std::cout, format)(journal->master, true,
|
|
||||||
display_predicate.get());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (command == "E") {
|
else if (command == "E") {
|
||||||
format_t format(first_line_format);
|
format_t format(first_line_format);
|
||||||
|
|
@ -657,7 +662,7 @@ int main(int argc, char * argv[])
|
||||||
format_equity formatter(std::cout, format, nformat,
|
format_equity formatter(std::cout, format, nformat,
|
||||||
display_predicate.get());
|
display_predicate.get());
|
||||||
walk_accounts(journal->master, formatter, predicate.get(),
|
walk_accounts(journal->master, formatter, predicate.get(),
|
||||||
xact_display_flags, true, 0, sort_order.get());
|
xact_display_flags, true, sort_order.get());
|
||||||
}
|
}
|
||||||
else if (command == "e") {
|
else if (command == "e") {
|
||||||
format_t format(first_line_format);
|
format_t format(first_line_format);
|
||||||
|
|
|
||||||
34
valexpr.cc
34
valexpr.cc
|
|
@ -158,18 +158,46 @@ void node_t::compute(balance_t& result, const details_t& details) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLEARED:
|
case CLEARED:
|
||||||
if (details.entry)
|
if (details.entry) {
|
||||||
result = details.entry->state == entry_t::CLEARED;
|
result = details.entry->state == entry_t::CLEARED;
|
||||||
|
}
|
||||||
|
else if (details.account) {
|
||||||
|
bool all_clear = true;
|
||||||
|
for (transactions_list::const_iterator i
|
||||||
|
= details.account->transactions.begin();
|
||||||
|
i != details.account->transactions.end();
|
||||||
|
i++)
|
||||||
|
if ((*i)->entry->state != entry_t::CLEARED) {
|
||||||
|
all_clear = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result = all_clear;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REAL:
|
case REAL:
|
||||||
if (details.xact)
|
if (details.xact) {
|
||||||
result = ! (details.xact->flags & TRANSACTION_VIRTUAL);
|
result = ! (details.xact->flags & TRANSACTION_VIRTUAL);
|
||||||
|
}
|
||||||
|
else if (details.account) {
|
||||||
|
bool all_real = true;
|
||||||
|
for (transactions_list::const_iterator i
|
||||||
|
= details.account->transactions.begin();
|
||||||
|
i != details.account->transactions.end();
|
||||||
|
i++)
|
||||||
|
if ((*i)->flags & TRANSACTION_VIRTUAL) {
|
||||||
|
all_real = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result = all_real;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX:
|
case INDEX:
|
||||||
if (details.xact)
|
if (details.xact)
|
||||||
result = details.xact->index + 1;
|
result = details.xact->index + 1;
|
||||||
|
else if (details.account)
|
||||||
|
result = details.account->depth - 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case F_ARITH_MEAN:
|
case F_ARITH_MEAN:
|
||||||
|
|
@ -359,7 +387,7 @@ node_t * parse_term(std::istream& in)
|
||||||
case 'd': node = new node_t(node_t::DATE); break;
|
case 'd': node = new node_t(node_t::DATE); break;
|
||||||
case 'X': node = new node_t(node_t::CLEARED); break;
|
case 'X': node = new node_t(node_t::CLEARED); break;
|
||||||
case 'R': node = new node_t(node_t::REAL); break;
|
case 'R': node = new node_t(node_t::REAL); break;
|
||||||
case 'i': node = new node_t(node_t::INDEX); break;
|
case 'n': node = new node_t(node_t::INDEX); break;
|
||||||
case 'B': node = new node_t(node_t::BALANCE); break;
|
case 'B': node = new node_t(node_t::BALANCE); break;
|
||||||
case 'T': node = new node_t(node_t::TOTAL); break;
|
case 'T': node = new node_t(node_t::TOTAL); break;
|
||||||
case 'C': node = new node_t(node_t::COST_TOTAL); break;
|
case 'C': node = new node_t(node_t::COST_TOTAL); break;
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ struct node_t
|
||||||
DATE,
|
DATE,
|
||||||
CLEARED,
|
CLEARED,
|
||||||
REAL,
|
REAL,
|
||||||
INDEX,
|
INDEX, // for accounts, this is the DEPTH
|
||||||
|
|
||||||
// Item totals
|
// Item totals
|
||||||
BALANCE,
|
BALANCE,
|
||||||
|
|
|
||||||
36
walk.h
36
walk.h
|
|
@ -154,25 +154,22 @@ inline void sort_accounts(account_t * account,
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
void walk__accounts(account_t * account,
|
void walk__accounts(account_t * account, const Function& functor)
|
||||||
const Function& functor,
|
|
||||||
const unsigned int max_depth)
|
|
||||||
{
|
{
|
||||||
functor(account, max_depth);
|
functor(account);
|
||||||
|
|
||||||
for (accounts_map::const_iterator i = account->accounts.begin();
|
for (accounts_map::const_iterator i = account->accounts.begin();
|
||||||
i != account->accounts.end();
|
i != account->accounts.end();
|
||||||
i++)
|
i++)
|
||||||
walk__accounts((*i).second, functor, max_depth);
|
walk__accounts((*i).second, functor);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
void walk__accounts_sorted(account_t * account,
|
void walk__accounts_sorted(account_t * account,
|
||||||
const Function& functor,
|
const Function& functor,
|
||||||
const unsigned int max_depth,
|
const node_t * sort_order)
|
||||||
const node_t * sort_order)
|
|
||||||
{
|
{
|
||||||
functor(account, max_depth);
|
functor(account);
|
||||||
|
|
||||||
accounts_deque accounts;
|
accounts_deque accounts;
|
||||||
|
|
||||||
|
|
@ -187,7 +184,7 @@ void walk__accounts_sorted(account_t * account,
|
||||||
for (accounts_deque::const_iterator i = accounts.begin();
|
for (accounts_deque::const_iterator i = accounts.begin();
|
||||||
i != accounts.end();
|
i != accounts.end();
|
||||||
i++)
|
i++)
|
||||||
walk__accounts_sorted(*i, functor, max_depth, sort_order);
|
walk__accounts_sorted(*i, functor, sort_order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
|
|
@ -217,13 +214,12 @@ inline void sum__accounts(account_t * account)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
void walk_accounts(account_t * account,
|
void walk_accounts(account_t * account,
|
||||||
const Function& functor,
|
const Function& functor,
|
||||||
const node_t * predicate,
|
const node_t * predicate,
|
||||||
unsigned int flags,
|
unsigned int flags,
|
||||||
const bool calc_subtotals,
|
const bool calc_subtotals,
|
||||||
const unsigned int max_depth,
|
const node_t * sort_order = NULL)
|
||||||
const node_t * sort_order = NULL)
|
|
||||||
{
|
{
|
||||||
item_predicate<transaction_t> pred_functor(predicate);
|
item_predicate<transaction_t> pred_functor(predicate);
|
||||||
|
|
||||||
|
|
@ -232,9 +228,9 @@ void walk_accounts(account_t * account,
|
||||||
sum__accounts(account);
|
sum__accounts(account);
|
||||||
|
|
||||||
if (sort_order)
|
if (sort_order)
|
||||||
walk__accounts_sorted<Function>(account, functor, max_depth, sort_order);
|
walk__accounts_sorted<Function>(account, functor, sort_order);
|
||||||
else
|
else
|
||||||
walk__accounts<Function>(account, functor, max_depth);
|
walk__accounts<Function>(account, functor);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue