diff options
-rw-r--r-- | src/chain.cc | 4 | ||||
-rw-r--r-- | src/filters.cc | 45 | ||||
-rw-r--r-- | src/filters.h | 28 | ||||
-rw-r--r-- | src/global.cc | 13 | ||||
-rw-r--r-- | src/output.cc | 78 | ||||
-rw-r--r-- | src/output.h | 23 | ||||
-rw-r--r-- | src/report.cc | 54 | ||||
-rw-r--r-- | src/report.h | 5 |
8 files changed, 110 insertions, 140 deletions
diff --git a/src/chain.cc b/src/chain.cc index 30a6793c..c67de108 100644 --- a/src/chain.cc +++ b/src/chain.cc @@ -113,7 +113,9 @@ xact_handler_ptr chain_xact_handlers(report_t& report, // // dow_xacts is like period_xacts, except that it reports all the xacts // that fall on each subsequent day of the week. - if (report.HANDLED(subtotal)) + if (report.HANDLED(equity)) + handler.reset(new xacts_as_equity(handler, expr)); + else if (report.HANDLED(subtotal)) handler.reset(new subtotal_xacts(handler, expr)); } diff --git a/src/filters.cc b/src/filters.cc index c5116b6c..651bc762 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -516,7 +516,7 @@ void interval_xacts::operator()(xact_t& xact) xact_temps.push_back(xact_t(&empty_account)); xact_t& null_xact = xact_temps.back(); - null_xact.add_flags(ITEM_TEMP); + null_xact.add_flags(ITEM_TEMP | XACT_CALCULATED); null_xact.amount = 0L; null_entry.add_xact(&null_xact); @@ -536,6 +536,49 @@ void interval_xacts::operator()(xact_t& xact) last_xact = &xact; } +void xacts_as_equity::report_subtotal() +{ + date_t finish; + foreach (xact_t * xact, component_xacts) { + date_t date = xact->reported_date(); + if (! is_valid(finish) || date > finish) + finish = date; + } + component_xacts.clear(); + + entry_temps.push_back(entry_t()); + entry_t& entry = entry_temps.back(); + entry.payee = "Opening Balances"; + entry._date = finish; + + value_t total = 0L; + foreach (values_map::value_type& pair, values) { + handle_value(pair.second.value, pair.second.account, &entry, 0, + xact_temps, *handler); + total += pair.second.value; + } + values.clear(); + + if (total.is_balance()) { + foreach (balance_t::amounts_map::value_type pair, + total.as_balance().amounts) { + xact_temps.push_back(xact_t(balance_account)); + xact_t& balance_xact = xact_temps.back(); + balance_xact.add_flags(ITEM_TEMP); + balance_xact.amount = - pair.second; + entry.add_xact(&balance_xact); + (*handler)(balance_xact); + } + } else { + xact_temps.push_back(xact_t(balance_account)); + xact_t& balance_xact = xact_temps.back(); + balance_xact.add_flags(ITEM_TEMP); + balance_xact.amount = - total.to_amount(); + entry.add_xact(&balance_xact); + (*handler)(balance_xact); + } +} + by_payee_xacts::~by_payee_xacts() { TRACE_DTOR(by_payee_xacts); diff --git a/src/filters.h b/src/filters.h index d5636796..985fbf94 100644 --- a/src/filters.h +++ b/src/filters.h @@ -611,6 +611,34 @@ public: virtual void operator()(xact_t& xact); }; +class xacts_as_equity : public subtotal_xacts +{ + interval_t interval; + xact_t * last_xact; + account_t equity_account; + account_t * balance_account; + + xacts_as_equity(); + +public: + xacts_as_equity(xact_handler_ptr _handler, expr_t& amount_expr) + : subtotal_xacts(_handler, amount_expr), + equity_account(NULL, "Equity") { + TRACE_CTOR(xacts_as_equity, "xact_handler_ptr, expr_t&"); + balance_account = equity_account.find_account("Opening Balances"); + } + virtual ~xacts_as_equity() throw() { + TRACE_DTOR(xacts_as_equity); + } + + void report_subtotal(); + + virtual void flush() { + report_subtotal(); + subtotal_xacts::flush(); + } +}; + /** * @brief Brief * diff --git a/src/global.cc b/src/global.cc index 0ecd1fb8..f967d3e9 100644 --- a/src/global.cc +++ b/src/global.cc @@ -339,7 +339,7 @@ void global_scope_t::normalize_session_options() function_t global_scope_t::look_for_precommand(scope_t& scope, const string& verb) { - if (expr_t::ptr_op_t def = scope.lookup(string("precmd_") + verb)) + if (expr_t::ptr_op_t def = scope.lookup(string(PRECMD_PREFIX) + verb)) return def->as_function(); else return function_t(); @@ -348,7 +348,7 @@ function_t global_scope_t::look_for_precommand(scope_t& scope, function_t global_scope_t::look_for_command(scope_t& scope, const string& verb) { - if (expr_t::ptr_op_t def = scope.lookup(string("cmd_") + verb)) + if (expr_t::ptr_op_t def = scope.lookup(string(CMD_PREFIX) + verb)) return def->as_function(); else return function_t(); @@ -361,7 +361,7 @@ void global_scope_t::normalize_report_options(const string& verb) report_t& rep(report()); - // jww (2009-02-09): These global are a hack, but hard to avoid + // jww (2009-02-09): These global are a hack, but hard to avoid. item_t::use_effective_date = rep.HANDLED(effective); if (rep.HANDLED(date_format_)) { @@ -369,14 +369,15 @@ void global_scope_t::normalize_report_options(const string& verb) output_date_format = rep.HANDLER(date_format_).str(); } - // jww (2008-08-14): This code really needs to be rationalized away - // for 3.0. + // jww (2008-08-14): This code really needs to be rationalized away for 3.0. + // I might be able to do it with command objects, like register_t, which + // each know how to adjust the report based on its current option settings. if (verb == "print" || verb == "entry" || verb == "dump") { rep.HANDLER(related).on_only(); rep.HANDLER(related_all).on_only(); } else if (verb == "equity") { - rep.HANDLER(subtotal).on_only(); + rep.HANDLER(equity).on_only(); } else if (rep.HANDLED(related)) { if (verb[0] == 'r') { diff --git a/src/output.cc b/src/output.cc index bd55fe99..2cc075eb 100644 --- a/src/output.cc +++ b/src/output.cc @@ -304,82 +304,4 @@ void format_accounts::operator()(account_t& account) posted_accounts.push_back(&account); } -format_equity::format_equity(report_t& _report, const string& _format) - : format_accounts(_report) -{ - const char * f = _format.c_str(); - - if (const char * p = std::strstr(f, "%/")) { - first_line_format.parse(string(f, 0, p - f)); - next_lines_format.parse(string(p + 2)); - } else { - first_line_format.parse(_format); - next_lines_format.parse(_format); - } - - entry_t header_entry; - header_entry.payee = "Opening Balances"; - header_entry._date = CURRENT_DATE(); - bind_scope_t bound_scope(report, header_entry); - first_line_format.format(report.output_stream, bound_scope); -} - -void format_equity::flush() -{ - account_t summary(NULL, "Equity:Opening Balances"); - - account_t::xdata_t& xdata(summary.xdata()); - std::ostream& out(report.output_stream); - - xdata.value = total.negate(); - - if (total.type() >= value_t::BALANCE) { - const balance_t * bal; - if (total.is_type(value_t::BALANCE)) - bal = &(total.as_balance()); - else - assert(false); - - foreach (balance_t::amounts_map::value_type pair, bal->amounts) { - xdata.value = pair.second; - xdata.value.negate(); - bind_scope_t bound_scope(report, summary); - next_lines_format.format(out, bound_scope); - } - } else { - bind_scope_t bound_scope(report, summary); - next_lines_format.format(out, bound_scope); - } - out.flush(); -} - -void format_equity::post_account(account_t& account) -{ - std::ostream& out(report.output_stream); - - if (! account.has_flags(ACCOUNT_EXT_MATCHING)) - return; - - value_t val = account.xdata().value; - - if (val.type() >= value_t::BALANCE) { - const balance_t * bal; - if (val.is_type(value_t::BALANCE)) - bal = &(val.as_balance()); - else - assert(false); - - foreach (balance_t::amounts_map::value_type pair, bal->amounts) { - account.xdata().value = pair.second; - bind_scope_t bound_scope(report, account); - next_lines_format.format(out, bound_scope); - } - account.xdata().value = val; - } else { - bind_scope_t bound_scope(report, account); - next_lines_format.format(out, bound_scope); - } - total += val; -} - } // namespace ledger diff --git a/src/output.h b/src/output.h index 7019b7b2..f638f4de 100644 --- a/src/output.h +++ b/src/output.h @@ -192,29 +192,6 @@ public: virtual void operator()(account_t& account); }; -/** - * @brief Brief - * - * Long. - */ -class format_equity : public format_accounts -{ - format_t first_line_format; - format_t next_lines_format; - - mutable value_t total; - - public: - format_equity(report_t& _report, - const string& _format); - virtual ~format_equity() { - TRACE_DTOR(format_equity); - } - - virtual void post_account(account_t& account); - virtual void flush(); -}; - } // namespace ledger #endif // _OUTPUT_H diff --git a/src/report.cc b/src/report.cc index d9e88634..da56e141 100644 --- a/src/report.cc +++ b/src/report.cc @@ -356,7 +356,7 @@ option_t<report_t> * report_t::lookup_option(const char * p) OPT(effective); else OPT(empty); else OPT_(end_); - else OPT(equity_format_); + else OPT(equity); break; case 'f': OPT(flat); @@ -475,10 +475,10 @@ expr_t::ptr_op_t report_t::lookup(const string& name) break; case 'c': - if (WANT_CMD()) { p += CMD_PREFIX_LEN; - switch (*p) { + if (WANT_CMD()) { const char * q = p + CMD_PREFIX_LEN; + switch (*q) { case 'b': - if (*(p + 1) == '\0' || is_eq(p, "bal") || is_eq(p, "balance")) + if (*(q + 1) == '\0' || is_eq(q, "bal") || is_eq(q, "balance")) return expr_t::op_t::wrap_functor (reporter<account_t, acct_handler_ptr, &report_t::accounts_report> (new format_accounts(*this, report_format(HANDLER(balance_format_)), @@ -486,7 +486,7 @@ expr_t::ptr_op_t report_t::lookup(const string& name) break; case 'c': - if (is_eq(p, "csv")) + if (is_eq(q, "csv")) return WRAP_FUNCTOR (reporter<> (new format_xacts(*this, report_format(HANDLER(csv_format_))), @@ -494,30 +494,30 @@ expr_t::ptr_op_t report_t::lookup(const string& name) break; case 'e': - if (is_eq(p, "equity")) - return expr_t::op_t::wrap_functor - (reporter<account_t, acct_handler_ptr, &report_t::accounts_report> - (new format_equity(*this, report_format(HANDLER(print_format_))), + if (is_eq(q, "equity")) + return WRAP_FUNCTOR + (reporter<> + (new format_xacts(*this, report_format(HANDLER(print_format_))), *this)); - else if (is_eq(p, "entry")) + else if (is_eq(q, "entry")) return WRAP_FUNCTOR(entry_command); - else if (is_eq(p, "emacs")) + else if (is_eq(q, "emacs")) return WRAP_FUNCTOR (reporter<>(new format_emacs_xacts(output_stream), *this)); break; case 'p': - if (*(p + 1) == '\0' || is_eq(p, "print")) + if (*(q + 1) == '\0' || is_eq(q, "print")) return WRAP_FUNCTOR (reporter<> (new format_xacts(*this, report_format(HANDLER(print_format_))), *this)); - else if (is_eq(p, "prices")) + else if (is_eq(q, "prices")) return expr_t::op_t::wrap_functor (reporter<xact_t, xact_handler_ptr, &report_t::commodities_report> (new format_xacts(*this, report_format(HANDLER(prices_format_))), *this)); - else if (is_eq(p, "pricesdb")) + else if (is_eq(q, "pricesdb")) return expr_t::op_t::wrap_functor (reporter<xact_t, xact_handler_ptr, &report_t::commodities_report> (new format_xacts(*this, report_format(HANDLER(pricesdb_format_))), @@ -525,17 +525,17 @@ expr_t::ptr_op_t report_t::lookup(const string& name) break; case 'r': - if (*(p + 1) == '\0' || is_eq(p, "reg") || is_eq(p, "register")) + if (*(q + 1) == '\0' || is_eq(q, "reg") || is_eq(q, "register")) return WRAP_FUNCTOR (reporter<> (new format_xacts(*this, report_format(HANDLER(register_format_))), *this)); - else if (is_eq(p, "reload")) + else if (is_eq(q, "reload")) return MAKE_FUNCTOR(report_t::reload_command); break; case 's': - if (is_eq(p, "stats") || is_eq(p, "stat")) + if (is_eq(q, "stats") || is_eq(q, "stat")) return WRAP_FUNCTOR(reporter<>(new gather_statistics(*this), *this)); break; } @@ -565,8 +565,8 @@ expr_t::ptr_op_t report_t::lookup(const string& name) break; case 'o': - if (WANT_OPT()) { p += OPT_PREFIX_LEN; - if (option_t<report_t> * handler = lookup_option(p)) + if (WANT_OPT()) { const char * q = p + OPT_PREFIX_LEN; + if (option_t<report_t> * handler = lookup_option(q)) return MAKE_OPT_HANDLER(report_t, handler); } else if (is_eq(p, "options")) { @@ -575,28 +575,28 @@ expr_t::ptr_op_t report_t::lookup(const string& name) break; case 'p': - if (WANT_PRECMD()) { p += PRECMD_PREFIX_LEN; - switch (*p) { + if (WANT_PRECMD()) { const char * q = p + PRECMD_PREFIX_LEN; + switch (*q) { case 'a': - if (is_eq(p, "args")) + if (is_eq(q, "args")) return WRAP_FUNCTOR(args_command); break; case 'e': - if (is_eq(p, "eval")) + if (is_eq(q, "eval")) return WRAP_FUNCTOR(eval_command); break; case 'f': - if (is_eq(p, "format")) + if (is_eq(q, "format")) return WRAP_FUNCTOR(format_command); break; case 'p': - if (is_eq(p, "parse")) + if (is_eq(q, "parse")) return WRAP_FUNCTOR(parse_command); - else if (is_eq(p, "period")) + else if (is_eq(q, "period")) return WRAP_FUNCTOR(period_command); break; case 't': - if (is_eq(p, "template")) + if (is_eq(q, "template")) return WRAP_FUNCTOR(template_command); break; } diff --git a/src/report.h b/src/report.h index 0e66ec75..47a073d1 100644 --- a/src/report.h +++ b/src/report.h @@ -354,10 +354,7 @@ public: #endif }); - OPTION__(report_t, equity_format_, CTOR(report_t, equity_format_) { - on("\n%D %Y%C%P\n%/ %-34W %12t\n"); - }); - + OPTION(report_t, equity); OPTION(report_t, flat); OPTION(report_t, forecast_); OPTION(report_t, format_); // -F |