got more reports working again
This commit is contained in:
parent
5db1e1165b
commit
c6c0179545
7 changed files with 161 additions and 230 deletions
91
format.cc
91
format.cc
|
|
@ -14,18 +14,22 @@ std::string truncated(const std::string& str, unsigned int width)
|
|||
return buf;
|
||||
}
|
||||
|
||||
std::string partial_account_name(const account_t * account,
|
||||
const unsigned int start_depth)
|
||||
std::string partial_account_name(const account_t * account)
|
||||
{
|
||||
std::string name = account->name;
|
||||
const account_t * acct = account->parent;
|
||||
std::string name;
|
||||
|
||||
for (int i = account->depth - start_depth - 1;
|
||||
--i >= 0 && acct->parent; ) {
|
||||
assert(acct);
|
||||
for (const account_t * acct = account;
|
||||
acct && acct->parent;
|
||||
acct = acct->parent) {
|
||||
if (acct->flags & ACCOUNT_DISPLAYED)
|
||||
break;
|
||||
|
||||
if (name.empty())
|
||||
name = acct->name;
|
||||
else
|
||||
name = acct->name + ":" + name;
|
||||
acct = acct->parent;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
|
@ -206,8 +210,7 @@ void format_t::format_elements(std::ostream& out,
|
|||
if (details.account) {
|
||||
std::string name = (elem->type == element_t::ACCOUNT_FULLNAME ?
|
||||
details.account->fullname() :
|
||||
partial_account_name(details.account,
|
||||
details.depth));
|
||||
partial_account_name(details.account));
|
||||
if (elem->max_width > 0)
|
||||
name = truncated(name, elem->max_width);
|
||||
|
||||
|
|
@ -278,7 +281,10 @@ void format_t::format_elements(std::ostream& out,
|
|||
}
|
||||
|
||||
case element_t::SPACER:
|
||||
for (unsigned int i = 0; i < details.depth; i++) {
|
||||
for (const account_t * acct = details.account;
|
||||
acct;
|
||||
acct = acct->parent)
|
||||
if (acct->flags & ACCOUNT_DISPLAYED) {
|
||||
if (elem->min_width > 0 || elem->max_width > 0)
|
||||
out.width(elem->min_width > elem->max_width ?
|
||||
elem->min_width : elem->max_width);
|
||||
|
|
@ -293,10 +299,11 @@ void format_t::format_elements(std::ostream& out,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef COLLAPSED_REGISTER
|
||||
|
||||
void format_transaction::report_cumulative_subtotal() const
|
||||
{
|
||||
if (count == 1) {
|
||||
if (! intercept || ! intercept(last_xact))
|
||||
first_line_format.format_elements(output_stream, details_t(last_xact));
|
||||
return;
|
||||
}
|
||||
|
|
@ -321,7 +328,6 @@ void format_transaction::report_cumulative_subtotal() const
|
|||
splits_total.cost = (*i).second;
|
||||
splits_total.total += (*i).second;
|
||||
if (first) {
|
||||
if (! intercept || ! intercept(&splits_total))
|
||||
first_line_format.format_elements(output_stream,
|
||||
details_t(&splits_total));
|
||||
first = false;
|
||||
|
|
@ -332,10 +338,12 @@ void format_transaction::report_cumulative_subtotal() const
|
|||
}
|
||||
}
|
||||
|
||||
#endif // COLLAPSED_REGISTER
|
||||
|
||||
void format_transaction::operator()(transaction_t * xact) const
|
||||
{
|
||||
if (last_xact)
|
||||
xact->total = last_xact->total;
|
||||
xact->total += last_xact->total;
|
||||
|
||||
if (inverted) {
|
||||
xact->amount.negate();
|
||||
|
|
@ -353,6 +361,7 @@ void format_transaction::operator()(transaction_t * xact) const
|
|||
// This makes the assumption that transactions from a single entry
|
||||
// are always grouped together.
|
||||
|
||||
#ifdef COLLAPSED_REGISTER
|
||||
if (collapsed) {
|
||||
// If we've reached a new entry, report on the subtotal
|
||||
// accumulated thus far.
|
||||
|
|
@ -365,9 +374,10 @@ void format_transaction::operator()(transaction_t * xact) const
|
|||
|
||||
subtotal += *xact;
|
||||
count++;
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (last_entry != xact->entry) {
|
||||
if (! intercept || ! intercept(xact))
|
||||
first_line_format.format_elements(output_stream, details_t(xact));
|
||||
} else {
|
||||
next_lines_format.format_elements(output_stream, details_t(xact));
|
||||
|
|
@ -383,38 +393,8 @@ void format_transaction::operator()(transaction_t * xact) const
|
|||
last_xact = xact;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
bool report_changed_values(transaction_t * xact)
|
||||
{
|
||||
static transaction_t * last_xact = NULL;
|
||||
|
||||
if (last_xact) {
|
||||
balance_t prev_bal, cur_bal;
|
||||
format_t::compute_total(prev_bal, details_t(last_xact));
|
||||
format_t::compute_total(cur_bal, details_t(xact));
|
||||
|
||||
if (balance_t diff = cur_bal - prev_bal) {
|
||||
entry_t modified_entry;
|
||||
transaction_t new_xact(&modified_entry, NULL);
|
||||
|
||||
modified_entry.date = xact ? xact->entry->date : std::time(NULL);
|
||||
modified_entry.payee = "Commodities revalued";
|
||||
|
||||
new_xact.amount = diff.amount();
|
||||
format_t::compute_value(diff, details_t(xact));
|
||||
new_xact.total = cur_bal - diff;
|
||||
|
||||
functor(&new_xact);
|
||||
}
|
||||
}
|
||||
|
||||
last_xact = xact;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void format_account::operator()(const account_t * account,
|
||||
void format_account::operator()(account_t * account,
|
||||
const unsigned int max_depth,
|
||||
const bool report_top) const
|
||||
{
|
||||
|
|
@ -425,7 +405,8 @@ void format_account::operator()(const account_t * account,
|
|||
// parent account and a lone displayed child, then don't display the
|
||||
// parent."
|
||||
|
||||
if (bool output = report_top || account->parent != NULL) {
|
||||
if (bool output = ((report_top || account->parent != NULL) &&
|
||||
disp_pred_functor(account))) {
|
||||
int counted = 0;
|
||||
bool display = false;
|
||||
|
||||
|
|
@ -445,17 +426,9 @@ void format_account::operator()(const account_t * account,
|
|||
if (counted == 1 && ! display)
|
||||
output = false;
|
||||
|
||||
if (output) {
|
||||
unsigned int depth = account->depth;
|
||||
if (max_depth == 0 || depth <= max_depth) {
|
||||
for (const account_t * acct = account;
|
||||
depth > 0 && acct && acct != last_account;
|
||||
acct = acct->parent)
|
||||
depth--;
|
||||
|
||||
format.format_elements(output_stream, details_t(account, depth));
|
||||
last_account = account;
|
||||
}
|
||||
if (output && (max_depth == 0 || account->depth <= max_depth)) {
|
||||
format.format_elements(output_stream, details_t(account));
|
||||
account->flags |= ACCOUNT_DISPLAYED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
92
format.h
92
format.h
|
|
@ -87,17 +87,17 @@ class format_transaction
|
|||
std::ostream& output_stream;
|
||||
const format_t& first_line_format;
|
||||
const format_t& next_lines_format;
|
||||
#ifdef COLLAPSED_REGISTER
|
||||
const bool collapsed;
|
||||
#endif
|
||||
const bool inverted;
|
||||
|
||||
item_predicate<transaction_t> disp_pred_functor;
|
||||
|
||||
typedef bool (*intercept_t)(transaction_t * xact);
|
||||
|
||||
intercept_t intercept;
|
||||
|
||||
#ifdef COLLAPSED_REGISTER
|
||||
mutable balance_pair_t subtotal;
|
||||
mutable unsigned int count;
|
||||
#endif
|
||||
mutable entry_t * last_entry;
|
||||
mutable transaction_t * last_xact;
|
||||
|
||||
|
|
@ -106,29 +106,86 @@ class format_transaction
|
|||
const format_t& _first_line_format,
|
||||
const format_t& _next_lines_format,
|
||||
const node_t * display_predicate,
|
||||
#ifdef COLLAPSED_REGISTER
|
||||
const bool _collapsed = false,
|
||||
const bool _inverted = false,
|
||||
intercept_t _intercept = NULL)
|
||||
#endif
|
||||
const bool _inverted = false)
|
||||
: output_stream(_output_stream),
|
||||
first_line_format(_first_line_format),
|
||||
next_lines_format(_next_lines_format),
|
||||
collapsed(_collapsed), inverted(_inverted),
|
||||
disp_pred_functor(display_predicate),
|
||||
intercept(_intercept), count(0),
|
||||
#ifdef COLLAPSED_REGISTER
|
||||
collapsed(_collapsed),
|
||||
#endif
|
||||
inverted(_inverted), disp_pred_functor(display_predicate),
|
||||
#ifdef COLLAPSED_REGISTER
|
||||
count(0),
|
||||
#endif
|
||||
last_entry(NULL), last_xact(NULL) {}
|
||||
|
||||
void start() const {}
|
||||
void finish() const {
|
||||
#ifdef COLLAPSED_REGISTER
|
||||
~format_transaction() {
|
||||
if (subtotal)
|
||||
report_cumulative_subtotal();
|
||||
}
|
||||
|
||||
void report_cumulative_subtotal() const;
|
||||
#endif
|
||||
|
||||
void operator()(transaction_t * xact) const;
|
||||
};
|
||||
|
||||
// An intercept that can be used to report changes in commodity value
|
||||
bool report_changed_values(transaction_t * xact);
|
||||
|
||||
template <typename Function>
|
||||
class changed_value_filter
|
||||
{
|
||||
const Function& functor;
|
||||
|
||||
mutable entry_t modified_entry;
|
||||
mutable transaction_t modified_xact;
|
||||
mutable transaction_t * last_xact;
|
||||
|
||||
public:
|
||||
changed_value_filter(const Function& _functor)
|
||||
: functor(_functor), modified_xact(&modified_entry, NULL),
|
||||
last_xact(NULL) {
|
||||
modified_entry.payee = "Commodities revalued";
|
||||
}
|
||||
|
||||
~changed_value_filter() {
|
||||
(*this)(NULL);
|
||||
}
|
||||
|
||||
void operator()(transaction_t * xact) const {
|
||||
if (last_xact) {
|
||||
balance_t prev_bal, cur_bal;
|
||||
|
||||
format_t::compute_total(prev_bal, details_t(last_xact));
|
||||
|
||||
std::time_t current = xact ? xact->entry->date : std::time(NULL);
|
||||
std::time_t prev_date = last_xact->entry->date;
|
||||
last_xact->entry->date = current;
|
||||
format_t::compute_total(cur_bal, details_t(last_xact));
|
||||
last_xact->entry->date = prev_date;
|
||||
|
||||
if (balance_t diff = cur_bal - prev_bal) {
|
||||
modified_entry.date = current;
|
||||
|
||||
// jww (2004-08-07): What if there are multiple commodities?
|
||||
assert(diff.amounts.size() == 1);
|
||||
modified_xact.amount = diff.amount();
|
||||
modified_xact.total = diff;
|
||||
modified_xact.total.negate();
|
||||
|
||||
functor(&modified_xact);
|
||||
}
|
||||
}
|
||||
|
||||
if (xact)
|
||||
functor(xact);
|
||||
|
||||
last_xact = xact;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class format_account
|
||||
|
|
@ -138,19 +195,14 @@ class format_account
|
|||
|
||||
item_predicate<account_t> disp_pred_functor;
|
||||
|
||||
mutable const account_t * last_account;
|
||||
|
||||
public:
|
||||
format_account(std::ostream& _output_stream,
|
||||
const format_t& _format,
|
||||
const node_t * display_predicate = NULL)
|
||||
: output_stream(_output_stream), format(_format),
|
||||
disp_pred_functor(display_predicate), last_account(NULL) {}
|
||||
disp_pred_functor(display_predicate) {}
|
||||
|
||||
void start() const {}
|
||||
void finish() const {}
|
||||
|
||||
void operator()(const account_t * account,
|
||||
void operator()(account_t * account,
|
||||
const unsigned int max_depth = 1,
|
||||
const bool report_top = false) const;
|
||||
};
|
||||
|
|
|
|||
5
ledger.h
5
ledger.h
|
|
@ -94,6 +94,8 @@ class entry_t
|
|||
};
|
||||
|
||||
|
||||
#define ACCOUNT_DISPLAYED 0x1
|
||||
|
||||
typedef std::map<const std::string, account_t *> accounts_map;
|
||||
typedef std::pair<const std::string, account_t *> accounts_pair;
|
||||
|
||||
|
|
@ -109,6 +111,7 @@ class account_t
|
|||
balance_pair_t value;
|
||||
balance_pair_t total;
|
||||
unsigned long ident;
|
||||
unsigned long flags;
|
||||
|
||||
mutable std::string _fullname;
|
||||
static unsigned long next_ident;
|
||||
|
|
@ -117,7 +120,7 @@ class account_t
|
|||
const std::string& _name = "",
|
||||
const std::string& _note = "")
|
||||
: parent(_parent), name(_name), note(_note),
|
||||
depth(parent ? parent->depth + 1 : 0) {}
|
||||
depth(parent ? parent->depth + 1 : 0), flags(0) {}
|
||||
|
||||
~account_t();
|
||||
|
||||
|
|
|
|||
141
main.cc
141
main.cc
|
|
@ -11,19 +11,8 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The command-line balance report
|
||||
//
|
||||
|
||||
static const std::string bal_fmt = "%20T %2_%-n\n";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The command-line register and print report
|
||||
//
|
||||
|
||||
static const std::string reg_fmt
|
||||
= "%10d %-.20p %-.22N %12.66t %12.80T\n\
|
||||
%/ %-.22N %12.66t %12.80T\n";
|
||||
|
|
@ -31,104 +20,6 @@ static const std::string reg_fmt
|
|||
static const std::string print_fmt
|
||||
= "\n%10d %X%C%p\n %-34N %12o\n%/ %-34N %12o\n";
|
||||
|
||||
#if 0
|
||||
|
||||
static void report_value_change(std::ostream& out,
|
||||
const std::time_t date,
|
||||
const balance_pair_t& balance,
|
||||
const balance_pair_t& prev_balance,
|
||||
const node_t * predicate,
|
||||
const format_t& first_line_format,
|
||||
const format_t& next_lines_format)
|
||||
{
|
||||
}
|
||||
|
||||
void register_report(std::ostream& out,
|
||||
item_t * top,
|
||||
const node_t * predicate,
|
||||
const node_t * sort_order,
|
||||
const format_t& first_line_format,
|
||||
const format_t& next_lines_format,
|
||||
const bool show_expanded)
|
||||
{
|
||||
if (sort_order)
|
||||
top->sort(sort_order);
|
||||
|
||||
balance_pair_t balance;
|
||||
balance_pair_t last_reported;
|
||||
account_t splits(NULL, "<Total>");
|
||||
value_predicate pred_obj(predicate);
|
||||
|
||||
for (items_deque::const_iterator i = top->subitems.begin();
|
||||
i != top->subitems.end();
|
||||
i++) {
|
||||
bool first = true;
|
||||
|
||||
if ((*i)->subitems.size() > 1 && ! show_expanded) {
|
||||
item_t summary(*i);
|
||||
summary.parent = *i;
|
||||
summary.account = &splits;
|
||||
|
||||
summary.value = 0;
|
||||
for (items_deque::const_iterator j = (*i)->subitems.begin();
|
||||
j != (*i)->subitems.end();
|
||||
j++)
|
||||
summary.value += (*j)->value;
|
||||
summary.total = balance + summary.value;
|
||||
|
||||
bool show = pred_obj(&summary);
|
||||
if (show && show_commodities_revalued)
|
||||
report_value_change(out, summary.date, balance, last_reported,
|
||||
predicate, first_line_format, next_lines_format);
|
||||
|
||||
balance += summary.value;
|
||||
|
||||
if (show) {
|
||||
if (! show_commodities_revalued_only)
|
||||
first_line_format.format_elements(out, &summary, top);
|
||||
|
||||
if (show_commodities_revalued)
|
||||
last_reported = balance;
|
||||
}
|
||||
} else {
|
||||
for (items_deque::const_iterator j = (*i)->subitems.begin();
|
||||
j != (*i)->subitems.end();
|
||||
j++) {
|
||||
(*j)->total = balance + (*j)->value;
|
||||
|
||||
bool show = pred_obj(*j);
|
||||
if (show && first && show_commodities_revalued) {
|
||||
report_value_change(out, (*i)->date, balance, last_reported,
|
||||
predicate, first_line_format, next_lines_format);
|
||||
if (show_commodities_revalued_only)
|
||||
first = false;
|
||||
}
|
||||
|
||||
balance += (*j)->value;
|
||||
|
||||
if (show) {
|
||||
if (! show_commodities_revalued_only) {
|
||||
if (first) {
|
||||
first = false;
|
||||
first_line_format.format_elements(out, *j, *i);
|
||||
} else {
|
||||
next_lines_format.format_elements(out, *j, *i);
|
||||
}
|
||||
}
|
||||
|
||||
if (show_commodities_revalued)
|
||||
last_reported = balance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (show_commodities_revalued)
|
||||
report_value_change(out, -1, balance, last_reported, predicate,
|
||||
first_line_format, next_lines_format);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void set_price_conversion(const std::string& setting)
|
||||
{
|
||||
|
|
@ -710,19 +601,18 @@ int main(int argc, char * argv[])
|
|||
|
||||
unsigned int xact_display_flags = MATCHING_TRANSACTIONS;
|
||||
|
||||
if (command == "p" || command == "e") {
|
||||
if (command == "p" || command == "e" || command == "E") {
|
||||
xact_display_flags |= OTHER_TRANSACTIONS;
|
||||
show_expanded = true;
|
||||
}
|
||||
else if (command == "E") {
|
||||
show_expanded = true;
|
||||
}
|
||||
else if (show_related && command == "r") {
|
||||
xact_display_flags = OTHER_TRANSACTIONS;
|
||||
show_inverted = true;
|
||||
}
|
||||
else if (show_related) {
|
||||
if (command == "r") {
|
||||
xact_display_flags = OTHER_TRANSACTIONS;
|
||||
show_inverted = true;
|
||||
} else {
|
||||
xact_display_flags |= OTHER_TRANSACTIONS;
|
||||
}
|
||||
}
|
||||
|
||||
const char * f;
|
||||
if (! format_string.empty())
|
||||
|
|
@ -737,11 +627,9 @@ int main(int argc, char * argv[])
|
|||
if (command == "b") {
|
||||
format_t format(f);
|
||||
format_account formatter(std::cout, format, display_predicate.get());
|
||||
formatter.start();
|
||||
walk_accounts(journal->master, formatter, predicate.get(),
|
||||
xact_display_flags, show_subtotals, show_expanded ? 0 : 1,
|
||||
sort_order.get());
|
||||
formatter.finish();
|
||||
|
||||
if (! display_predicate.get() ||
|
||||
item_predicate<account_t>(display_predicate.get())(journal->master)) {
|
||||
|
|
@ -766,12 +654,20 @@ int main(int argc, char * argv[])
|
|||
|
||||
format_transaction formatter(std::cout, format, nformat,
|
||||
display_predicate.get(),
|
||||
! show_subtotals, show_inverted);
|
||||
formatter.start();
|
||||
|
||||
#ifdef COLLAPSED_REGISTER
|
||||
! show_subtotals,
|
||||
#endif
|
||||
show_inverted);
|
||||
if (! sort_order.get()) {
|
||||
if (show_commodities_revalued) {
|
||||
changed_value_filter<format_transaction>
|
||||
filtered_formatter(formatter);
|
||||
walk_entries(journal->entries.begin(), journal->entries.end(),
|
||||
filtered_formatter, predicate.get(), xact_display_flags);
|
||||
} else {
|
||||
walk_entries(journal->entries.begin(), journal->entries.end(),
|
||||
formatter, predicate.get(), xact_display_flags);
|
||||
}
|
||||
} else {
|
||||
transactions_deque transactions_pool;
|
||||
walk_entries(journal->entries.begin(), journal->entries.end(),
|
||||
|
|
@ -782,7 +678,6 @@ int main(int argc, char * argv[])
|
|||
walk_transactions(transactions_pool.begin(), transactions_pool.end(),
|
||||
formatter);
|
||||
}
|
||||
formatter.finish();
|
||||
}
|
||||
|
||||
// Save the cache, if need be
|
||||
|
|
|
|||
16
valexpr.cc
16
valexpr.cc
|
|
@ -153,6 +153,8 @@ void node_t::compute(balance_t& result, const details_t& details) const
|
|||
case DATE:
|
||||
if (details.entry)
|
||||
result = (unsigned int) details.entry->date;
|
||||
else
|
||||
result = (unsigned int) std::time(NULL);
|
||||
break;
|
||||
|
||||
case CLEARED:
|
||||
|
|
@ -207,12 +209,20 @@ void node_t::compute(balance_t& result, const details_t& details) const
|
|||
left->compute(result, details);
|
||||
|
||||
std::time_t moment = -1;
|
||||
if (right && details.entry) {
|
||||
if (right) {
|
||||
switch (right->type) {
|
||||
case DATE: moment = details.entry->date; break;
|
||||
case DATE:
|
||||
if (details.entry)
|
||||
moment = details.entry->date;
|
||||
else
|
||||
moment = std::time(NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw compute_error("Invalid date passed to P(v,d)");
|
||||
throw compute_error("Invalid date passed to P(value,date)");
|
||||
}
|
||||
} else {
|
||||
moment = std::time(NULL);
|
||||
}
|
||||
result = result.value(moment);
|
||||
break;
|
||||
|
|
|
|||
10
valexpr.h
10
valexpr.h
|
|
@ -33,17 +33,15 @@ struct details_t
|
|||
const entry_t * entry;
|
||||
const transaction_t * xact;
|
||||
const account_t * account;
|
||||
const unsigned int depth;
|
||||
|
||||
details_t(const entry_t * _entry)
|
||||
: entry(_entry), xact(NULL), account(NULL), depth(0) {}
|
||||
: entry(_entry), xact(NULL), account(NULL) {}
|
||||
|
||||
details_t(const transaction_t * _xact)
|
||||
: entry(_xact->entry), xact(_xact), account(_xact->account), depth(0) {}
|
||||
: entry(_xact->entry), xact(_xact), account(_xact->account) {}
|
||||
|
||||
details_t(const account_t * _account,
|
||||
const unsigned int _depth = 0)
|
||||
: entry(NULL), xact(NULL), account(_account), depth(_depth) {}
|
||||
details_t(const account_t * _account)
|
||||
: entry(NULL), xact(NULL), account(_account) {}
|
||||
};
|
||||
|
||||
struct node_t
|
||||
|
|
|
|||
4
walk.h
4
walk.h
|
|
@ -161,7 +161,7 @@ inline void sort_accounts(account_t * account,
|
|||
}
|
||||
|
||||
template <typename Function>
|
||||
void walk__accounts(const account_t * account,
|
||||
void walk__accounts(account_t * account,
|
||||
const Function& functor,
|
||||
const unsigned int max_depth)
|
||||
{
|
||||
|
|
@ -174,7 +174,7 @@ void walk__accounts(const account_t * account,
|
|||
}
|
||||
|
||||
template <typename Function>
|
||||
void walk__accounts_sorted(const account_t * account,
|
||||
void walk__accounts_sorted(account_t * account,
|
||||
const Function& functor,
|
||||
const unsigned int max_depth,
|
||||
const node_t * sort_order)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue