#include "walk.h" #include "format.h" #include "textual.h" #include "util.h" #include namespace ledger { std::list transactions_xdata; std::list transactions_xdata_ptrs; std::list accounts_xdata; std::list accounts_xdata_ptrs; template <> bool compare_items::operator()(const transaction_t * left, const transaction_t * right) { assert(left); assert(right); transaction_xdata_t& lxdata(transaction_xdata(*left)); if (! (lxdata.dflags & TRANSACTION_SORT_CALC)) { sort_order->compute(lxdata.sort_value, details_t(*left)); lxdata.dflags |= TRANSACTION_SORT_CALC; } transaction_xdata_t& rxdata(transaction_xdata(*right)); if (! (rxdata.dflags & TRANSACTION_SORT_CALC)) { sort_order->compute(rxdata.sort_value, details_t(*right)); rxdata.dflags |= TRANSACTION_SORT_CALC; } return lxdata.sort_value < rxdata.sort_value; } transaction_xdata_t& transaction_xdata(const transaction_t& xact) { if (! xact.data) { transactions_xdata.push_back(transaction_xdata_t()); xact.data = &transactions_xdata.back(); transactions_xdata_ptrs.push_back(&xact.data); } return *((transaction_xdata_t *) xact.data); } void add_transaction_to(const transaction_t& xact, value_t& value) { if (transaction_has_xdata(xact) && transaction_xdata_(xact).dflags & TRANSACTION_COMPOSITE) value += transaction_xdata_(xact).composite_amount; else if (xact.cost || value) value.add(xact.amount, xact.cost); else value = xact.amount; } void set_account_value::operator()(transaction_t& xact) { add_transaction_to(xact, account_xdata(*xact.account).value); account_xdata_(*xact.account).count++; if (xact.flags & TRANSACTION_VIRTUAL) account_xdata_(*xact.account).virtuals++; item_handler::operator()(xact); } void sort_transactions::flush() { std::stable_sort(transactions.begin(), transactions.end(), compare_items(sort_order)); for (transactions_deque::iterator i = transactions.begin(); i != transactions.end(); i++) { transaction_xdata(**i).dflags &= ~TRANSACTION_SORT_CALC; item_handler::operator()(**i); } item_handler::flush(); transactions.clear(); } void calc_transactions::operator()(transaction_t& xact) { transaction_xdata_t& xdata(transaction_xdata(xact)); if (last_xact && transaction_has_xdata(*last_xact)) { xdata.total += transaction_xdata_(*last_xact).total; xdata.index = transaction_xdata_(*last_xact).index + 1; } else { xdata.index = 0; } if (! (xdata.dflags & TRANSACTION_NO_TOTAL)) add_transaction_to(xact, xdata.total); item_handler::operator()(xact); last_xact = &xact; } void invert_transactions::operator()(transaction_t& xact) { if (transaction_has_xdata(xact) && transaction_xdata_(xact).dflags & TRANSACTION_COMPOSITE) { transaction_xdata_(xact).composite_amount.negate(); } else { xact.amount.negate(); if (xact.cost) xact.cost->negate(); } item_handler::operator()(xact); } static inline void handle_value(const value_t& value, account_t * account, entry_t * entry, unsigned int flags, std::list& temps, item_handler& handler, const std::time_t date = 0) { temps.push_back(transaction_t(account)); transaction_t& xact(temps.back()); xact.entry = entry; xact.flags |= TRANSACTION_BULK_ALLOC; entry->add_transaction(&xact); // If the account for this transaction is all virtual, then report // the transaction as such. This allows subtotal reports to show // "(Account)" for accounts that contain only virtual transactions. if (account && account_has_xdata(*account)) if (! (account_xdata_(*account).dflags & ACCOUNT_HAS_NON_VIRTUALS)) { xact.flags |= TRANSACTION_VIRTUAL; if (! (account_xdata_(*account).dflags & ACCOUNT_HAS_UNB_VIRTUALS)) xact.flags |= TRANSACTION_BALANCE; } transaction_xdata_t& xdata(transaction_xdata(xact)); switch (value.type) { case value_t::BOOLEAN: xact.amount = *((bool *) value.data); break; case value_t::INTEGER: xact.amount = *((long *) value.data); break; case value_t::AMOUNT: xact.amount = *((amount_t *) value.data); break; case value_t::BALANCE: case value_t::BALANCE_PAIR: xdata.composite_amount = value; flags |= TRANSACTION_COMPOSITE; break; } if (date) xdata.date = date; if (flags) xdata.dflags |= flags; handler(xact); } void collapse_transactions::report_subtotal() { assert(count >= 1); if (count == 1) { item_handler::operator()(*last_xact); } else { entry_temps.push_back(entry_t()); entry_t& entry = entry_temps.back(); entry.payee = last_entry->payee; entry.date = last_entry->date; handle_value(subtotal, &totals_account, last_entry, 0, xact_temps, *handler); } last_entry = NULL; last_xact = NULL; subtotal = 0L; count = 0; } void collapse_transactions::operator()(transaction_t& xact) { // If we've reached a new entry, report on the subtotal // accumulated thus far. if (last_entry && last_entry != xact.entry && count > 0) report_subtotal(); add_transaction_to(xact, subtotal); count++; last_entry = xact.entry; last_xact = &xact; } void related_transactions::flush() { if (transactions.size() > 0) for (transactions_list::iterator i = transactions.begin(); i != transactions.end(); i++) for (transactions_list::iterator j = (*i)->entry->transactions.begin(); j != (*i)->entry->transactions.end(); j++) { transaction_xdata_t& xdata = transaction_xdata(**j); if (! (xdata.dflags & TRANSACTION_HANDLED) && (! (xdata.dflags & TRANSACTION_RECEIVED) ? ! ((*j)->flags & (TRANSACTION_AUTO | TRANSACTION_VIRTUAL)) : also_matching)) { xdata.dflags |= TRANSACTION_HANDLED; item_handler::operator()(**j); } } item_handler::flush(); } void changed_value_transactions::output_diff(const std::time_t current) { value_t cur_bal; transaction_xdata(*last_xact).date = current; compute_total(cur_bal, details_t(*last_xact)); cur_bal.round(); transaction_xdata(*last_xact).date = 0; if (value_t diff = cur_bal - last_balance) { entry_temps.push_back(entry_t()); entry_t& entry = entry_temps.back(); entry.payee = "Commodities revalued"; entry.date = current; handle_value(diff, NULL, &entry, TRANSACTION_NO_TOTAL, xact_temps, *handler); } } void changed_value_transactions::operator()(transaction_t& xact) { if (last_xact) { std::time_t moment = 0; if (transaction_has_xdata(*last_xact)) moment = transaction_xdata_(*last_xact).date; if (! moment) moment = xact.entry->date; output_diff(moment); } if (changed_values_only) transaction_xdata(xact).dflags |= TRANSACTION_DISPLAYED; item_handler::operator()(xact); compute_total(last_balance, details_t(xact)); last_balance.round(); last_xact = &xact; } void subtotal_transactions::report_subtotal(const char * spec_fmt) { char buf[256]; if (! spec_fmt) { std::string fmt = "- "; fmt += format_t::date_format; std::strftime(buf, 255, fmt.c_str(), std::localtime(&finish)); } else { std::strftime(buf, 255, spec_fmt, std::localtime(&finish)); } entry_temps.push_back(entry_t()); entry_t& entry = entry_temps.back(); entry.payee = buf; entry.date = start; for (values_map::iterator i = values.begin(); i != values.end(); i++) handle_value((*i).second, (*i).first, &entry, 0, xact_temps, *handler, finish); values.clear(); } void subtotal_transactions::operator()(transaction_t& xact) { if (! start || std::difftime(xact.entry->date, start) < 0) start = xact.entry->date; if (! finish || std::difftime(xact.entry->date, finish) > 0) finish = xact.entry->date; values_map::iterator i = values.find(xact.account); if (i == values.end()) { value_t temp; add_transaction_to(xact, temp); values.insert(values_pair(xact.account, temp)); } else { add_transaction_to(xact, (*i).second); } // If the account for this transaction is all virtual, mark it as // such, so that `handle_value' can show "(Account)" for accounts // that contain only virtual transactions. if (! (xact.flags & TRANSACTION_VIRTUAL)) account_xdata(*xact.account).dflags |= ACCOUNT_HAS_NON_VIRTUALS; else if (! (xact.flags & TRANSACTION_BALANCE)) account_xdata(*xact.account).dflags |= ACCOUNT_HAS_UNB_VIRTUALS; } void interval_transactions::report_subtotal(const std::time_t moment) { assert(last_xact); start = interval.begin; if (moment) finish = moment - 86400; else finish = last_xact->entry->date; subtotal_transactions::report_subtotal(); if (sorter) subtotal_transactions::flush(); last_xact = NULL; } void interval_transactions::operator()(transaction_t& xact) { const std::time_t date = xact.entry->date; if ((interval.begin && std::difftime(date, interval.begin) < 0) || (interval.end && std::difftime(date, interval.end) >= 0)) return; if (interval) { if (! started) { if (! interval.begin) interval.start(date); start = interval.begin; started = true; } std::time_t quant = interval.increment(interval.begin); if (std::difftime(date, quant) >= 0) { if (last_xact) report_subtotal(quant); std::time_t temp; while (std::difftime(date, temp = interval.increment(quant)) >= 0) { if (quant == temp) break; quant = temp; } start = interval.begin = quant; } subtotal_transactions::operator()(xact); } else { item_handler::operator()(xact); } last_xact = &xact; } by_payee_transactions::~by_payee_transactions() { for (payee_subtotals_map::iterator i = payee_subtotals.begin(); i != payee_subtotals.end(); i++) delete (*i).second; } void by_payee_transactions::flush() { for (payee_subtotals_map::iterator i = payee_subtotals.begin(); i != payee_subtotals.end(); i++) (*i).second->report_subtotal((*i).first.c_str()); item_handler::flush(); payee_subtotals.clear(); } void by_payee_transactions::operator()(transaction_t& xact) { payee_subtotals_map::iterator i = payee_subtotals.find(xact.entry->payee); if (i == payee_subtotals.end()) { payee_subtotals_pair temp(xact.entry->payee, new subtotal_transactions(handler)); std::pair result = payee_subtotals.insert(temp); assert(result.second); if (! result.second) return; i = result.first; } if (std::difftime(xact.entry->date, (*i).second->start) > 0) (*i).second->start = xact.entry->date; (*(*i).second)(xact); } void set_comm_as_payee::operator()(transaction_t& xact) { entry_temps.push_back(*xact.entry); entry_t& entry = entry_temps.back(); entry.date = xact.entry->date; entry.state = xact.entry->state; entry.code = xact.entry->code; entry.payee = xact.amount.commodity().symbol; xact_temps.push_back(xact); transaction_t& temp = xact_temps.back(); temp.entry = &entry; temp.flags |= TRANSACTION_BULK_ALLOC; entry.add_transaction(&temp); item_handler::operator()(temp); } void dow_transactions::flush() { for (int i = 0; i < 7; i++) { start = finish = 0; for (transactions_list::iterator d = days_of_the_week[i].begin(); d != days_of_the_week[i].end(); d++) subtotal_transactions::operator()(**d); subtotal_transactions::report_subtotal("%As"); days_of_the_week[i].clear(); } subtotal_transactions::flush(); } void generate_transactions::add_period_entries (period_entries_list& period_entries) { for (period_entries_list::iterator i = period_entries.begin(); i != period_entries.end(); i++) for (transactions_list::iterator j = (*i)->transactions.begin(); j != (*i)->transactions.end(); j++) add_transaction((*i)->period, **j); } void generate_transactions::add_transaction(const interval_t& period, transaction_t& xact) { pending_xacts.push_back(pending_xacts_pair(period, &xact)); } void budget_transactions::report_budget_items(const std::time_t moment) { if (pending_xacts.size() > 0) { std::list to_clear; bool reported; do { reported = false; for (pending_xacts_list::iterator i = pending_xacts.begin(); i != pending_xacts.end(); i++) { std::time_t& begin = (*i).first.begin; if (! begin) { (*i).first.start(moment); begin = (*i).first.begin; } if (std::difftime(begin, moment) < 0 && (! (*i).first.end || std::difftime(begin, (*i).first.end) < 0)) { transaction_t& xact = *(*i).second; DEBUG_PRINT("ledger.walk.budget", "Reporting budget for " << xact.account->fullname()); DEBUG_PRINT_TIME("ledger.walk.budget", begin); DEBUG_PRINT_TIME("ledger.walk.budget", moment); entry_temps.push_back(entry_t()); entry_t& entry = entry_temps.back(); entry.payee = "Budget entry"; entry.date = begin; xact_temps.push_back(xact); transaction_t& temp = xact_temps.back(); temp.entry = &entry; temp.flags |= TRANSACTION_AUTO; temp.amount.negate(); temp.flags |= TRANSACTION_BULK_ALLOC; entry.add_transaction(&temp); begin = (*i).first.increment(begin); item_handler::operator()(temp); reported = true; } } } while (reported); for (std::list::iterator i = to_clear.begin(); i != to_clear.end(); i++) pending_xacts.erase(*i); } } void budget_transactions::operator()(transaction_t& xact) { bool xact_in_budget = false; for (pending_xacts_list::iterator i = pending_xacts.begin(); i != pending_xacts.end(); i++) for (account_t * acct = xact.account; acct; acct = acct->parent) { if (acct == (*i).second->account) { xact_in_budget = true; // Report the transaction as if it had occurred in the parent // account. if (xact.account != acct) xact.account = acct; goto handle; } } handle: if (xact_in_budget && flags & BUDGET_BUDGETED) { report_budget_items(xact.entry->date); item_handler::operator()(xact); } else if (! xact_in_budget && flags & BUDGET_UNBUDGETED) { item_handler::operator()(xact); } } void forecast_transactions::add_transaction(const interval_t& period, transaction_t& xact) { generate_transactions::add_transaction(period, xact); interval_t& i = pending_xacts.back().first; if (! i.begin) { i.start(now); i.begin = i.increment(i.begin); } else { while (std::difftime(i.begin, now) < 0) i.begin = i.increment(i.begin); } } void forecast_transactions::flush() { transactions_list passed; std::time_t last = 0; while (pending_xacts.size() > 0) { pending_xacts_list::iterator least = pending_xacts.begin(); for (pending_xacts_list::iterator i = ++pending_xacts.begin(); i != pending_xacts.end(); i++) if (std::difftime((*i).first.begin, (*least).first.begin) < 0) least = i; std::time_t& begin = (*least).first.begin; if ((*least).first.end && std::difftime(begin, (*least).first.end) >= 0) { pending_xacts.erase(least); passed.remove((*least).second); continue; } transaction_t& xact = *(*least).second; entry_temps.push_back(entry_t()); entry_t& entry = entry_temps.back(); entry.payee = "Forecast entry"; entry.date = begin; xact_temps.push_back(xact); transaction_t& temp = xact_temps.back(); temp.entry = &entry; temp.flags |= TRANSACTION_AUTO; temp.flags |= TRANSACTION_BULK_ALLOC; entry.add_transaction(&temp); std::time_t next = (*least).first.increment(begin); if (std::difftime(next, begin) < 0 || // wraparound (last && std::difftime(next, last) > 5 * 365 * 24 * 60 * 60)) break; begin = next; item_handler::operator()(temp); if (transaction_has_xdata(temp) && transaction_xdata_(temp).dflags & TRANSACTION_MATCHES) { if (! pred(temp)) break; last = temp.entry->date; passed.clear(); } else { bool found = false; for (transactions_list::iterator i = passed.begin(); i != passed.end(); i++) if (*i == &xact) { found = true; break; } if (! found) { passed.push_back(&xact); if (passed.size() >= pending_xacts.size()) break; } } } item_handler::flush(); } void clear_transactions_xdata() { transactions_xdata.clear(); for (std::list::iterator i = transactions_xdata_ptrs.begin(); i != transactions_xdata_ptrs.end(); i++) **i = NULL; } template <> bool compare_items::operator()(const account_t * left, const account_t * right) { assert(left); assert(right); account_xdata_t& lxdata(account_xdata(*left)); if (! (lxdata.dflags & ACCOUNT_SORT_CALC)) { sort_order->compute(lxdata.sort_value, details_t(*left)); lxdata.dflags |= ACCOUNT_SORT_CALC; } account_xdata_t& rxdata(account_xdata(*right)); if (! (rxdata.dflags & ACCOUNT_SORT_CALC)) { sort_order->compute(rxdata.sort_value, details_t(*right)); rxdata.dflags |= ACCOUNT_SORT_CALC; } return lxdata.sort_value < rxdata.sort_value; } account_xdata_t& account_xdata(const account_t& account) { if (! account.data) { accounts_xdata.push_back(account_xdata_t()); account.data = &accounts_xdata.back(); accounts_xdata_ptrs.push_back(&account.data); } return *((account_xdata_t *) account.data); } void sum_accounts(account_t& account) { account_xdata_t& xdata(account_xdata(account)); for (accounts_map::iterator i = account.accounts.begin(); i != account.accounts.end(); i++) { sum_accounts(*(*i).second); xdata.total += account_xdata_(*(*i).second).total; xdata.total_count += (account_xdata_(*(*i).second).total_count + account_xdata_(*(*i).second).count); } value_t result; compute_amount(result, details_t(account)); if (result) xdata.total += result; xdata.total_count += xdata.count; } void sort_accounts(account_t& account, const value_expr_t * sort_order, accounts_deque& accounts) { 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(sort_order)); } void walk_accounts(account_t& account, item_handler& handler, const value_expr_t * sort_order) { handler(account); if (sort_order) { accounts_deque accounts; sort_accounts(account, sort_order, accounts); for (accounts_deque::const_iterator i = accounts.begin(); i != accounts.end(); i++) { account_xdata(**i).dflags &= ~ACCOUNT_SORT_CALC; walk_accounts(**i, handler, sort_order); } } else { for (accounts_map::const_iterator i = account.accounts.begin(); i != account.accounts.end(); i++) walk_accounts(*(*i).second, handler, NULL); } } void walk_accounts(account_t& account, item_handler& handler, const std::string& sort_string) { if (! sort_string.empty()) { std::auto_ptr sort_order; try { sort_order.reset(parse_value_expr(sort_string)); } catch (value_expr_error& err) { throw error(std::string("In sort string '" + sort_string + "': " + err.what())); } walk_accounts(account, handler, sort_order.get()); } else { walk_accounts(account, handler); } } void clear_accounts_xdata() { accounts_xdata.clear(); for (std::list::iterator i = accounts_xdata_ptrs.begin(); i != accounts_xdata_ptrs.end(); i++) **i = NULL; } void walk_commodities(commodities_map& commodities, item_handler& handler) { std::list xact_temps; std::list entry_temps; std::list acct_temps; for (commodities_map::iterator i = commodities.begin(); i != commodities.end(); i++) { if ((*i).second->flags & COMMODITY_STYLE_NOMARKET) continue; entry_temps.push_back(entry_t()); acct_temps.push_back(account_t(NULL, (*i).second->symbol)); if ((*i).second->history) for (history_map::iterator j = (*i).second->history->prices.begin(); j != (*i).second->history->prices.end(); j++) { entry_temps.back().date = (*j).first; xact_temps.push_back(transaction_t(&acct_temps.back())); transaction_t& temp = xact_temps.back(); temp.entry = &entry_temps.back(); temp.amount = (*j).second; temp.flags |= TRANSACTION_BULK_ALLOC; entry_temps.back().add_transaction(&temp); handler(xact_temps.back()); } } handler.flush(); clear_entries_transactions(entry_temps); } } // namespace ledger #ifdef USE_BOOST_PYTHON #include using namespace boost::python; using namespace ledger; template struct item_handler_wrap : public item_handler { PyObject * self; item_handler_wrap(PyObject * self_) : self(self_) {} item_handler_wrap(PyObject * self_, const item_handler& _handler) : item_handler(const_cast *>(&_handler)), self(self_) {} item_handler_wrap(PyObject * self_, item_handler * _handler) : item_handler(_handler), self(self_) {} virtual void flush() { call_method(self, "flush"); } void default_flush() { item_handler::flush(); } virtual void operator()(T& item) { call_method(self, "__call__", ptr(&item)); } void default_call(T& item) { item_handler::operator()(item); } }; void (subtotal_transactions::*subtotal_transactions_flush)() = &subtotal_transactions::flush; void py_walk_entries(journal_t& journal, item_handler& handler) { walk_entries(journal.entries, handler); } void py_walk_transactions(entry_t& entry, item_handler& handler) { walk_transactions(entry.transactions, handler); } void py_walk_accounts_1(account_t& account, item_handler& handler) { walk_accounts(account, handler); } void py_walk_accounts_2(account_t& account, item_handler& handler, const value_expr_t * sort_order) { walk_accounts(account, handler, sort_order); } void py_walk_accounts_3(account_t& account, item_handler& handler, const std::string& sort_string) { walk_accounts(account, handler, sort_string); } void py_walk_commodities(item_handler& handler) { walk_commodities(commodity_t::commodities, handler); } void py_add_period_entries(generate_transactions& handler, journal_t * journal) { handler.add_period_entries(journal->period_entries); } void export_walk() { typedef item_handler xact_handler_t; scope().attr("TRANSACTION_RECEIVED") = TRANSACTION_RECEIVED; scope().attr("TRANSACTION_HANDLED") = TRANSACTION_HANDLED; scope().attr("TRANSACTION_TO_DISPLAY") = TRANSACTION_TO_DISPLAY; scope().attr("TRANSACTION_DISPLAYED") = TRANSACTION_DISPLAYED; scope().attr("TRANSACTION_NO_TOTAL") = TRANSACTION_NO_TOTAL; scope().attr("TRANSACTION_SORT_CALC") = TRANSACTION_SORT_CALC; scope().attr("TRANSACTION_COMPOSITE") = TRANSACTION_COMPOSITE; scope().attr("TRANSACTION_MATCHES") = TRANSACTION_MATCHES; class_< transaction_xdata_t > ("TransactionXData") .def_readwrite("total", &transaction_xdata_t::total) .def_readwrite("sort_value", &transaction_xdata_t::sort_value) .def_readwrite("composite_amount", &transaction_xdata_t::composite_amount) .def_readwrite("index", &transaction_xdata_t::index) .def_readwrite("dflags", &transaction_xdata_t::dflags) ; def("transaction_has_xdata", transaction_has_xdata); def("transaction_xdata", transaction_xdata, return_internal_reference<1>()); def("clear_transactions_xdata", clear_transactions_xdata); def("add_transaction_to", add_transaction_to); class_< xact_handler_t, item_handler_wrap > ("TransactionHandler") .def(init()[with_custodian_and_ward<1, 2>()]) .def("flush", &xact_handler_t::flush, &item_handler_wrap::default_flush) .def("__call__", &xact_handler_t::operator(), &item_handler_wrap::default_call) ; class_< ignore_transactions, bases > ("IgnoreTransactions") .def("flush", &xact_handler_t::flush) .def("__call__", &ignore_transactions::operator()); ; class_< set_account_value, bases > ("SetAccountValue") .def(init()[with_custodian_and_ward<1, 2>()]) .def("flush", &xact_handler_t::flush) .def("__call__", &set_account_value::operator()); ; class_< sort_transactions, bases > ("SortTransactions", init() [with_custodian_and_ward<1, 2>()]) .def(init() [with_custodian_and_ward<1, 2>()]) .def("flush", &sort_transactions::flush) .def("__call__", &sort_transactions::operator()); ; class_< filter_transactions, bases > ("FilterTransactions", init() [with_custodian_and_ward<1, 2>()]) .def(init() [with_custodian_and_ward<1, 2>()]) .def("flush", &xact_handler_t::flush) .def("__call__", &filter_transactions::operator()); ; class_< calc_transactions, bases > ("CalcTransactions", init() [with_custodian_and_ward<1, 2>()]) .def("flush", &xact_handler_t::flush) .def("__call__", &calc_transactions::operator()); ; class_< invert_transactions, bases > ("InvertTransactions", init() [with_custodian_and_ward<1, 2>()]) .def("flush", &xact_handler_t::flush) .def("__call__", &invert_transactions::operator()); ; class_< collapse_transactions, bases > ("CollapseTransactions", init() [with_custodian_and_ward<1, 2>()]) .def("flush", &collapse_transactions::flush) .def("__call__", &collapse_transactions::operator()); ; class_< related_transactions, bases > ("RelatedTransactions", init >() [with_custodian_and_ward<1, 2>()]) .def("flush", &xact_handler_t::flush) .def("__call__", &related_transactions::operator()); ; class_< changed_value_transactions, bases > ("ChangeValueTransactions", init() [with_custodian_and_ward<1, 2>()]) .def("flush", &changed_value_transactions::flush) .def("__call__", &changed_value_transactions::operator()); ; class_< subtotal_transactions, bases > ("SubtotalTransactions", init() [with_custodian_and_ward<1, 2>()]) .def("flush", subtotal_transactions_flush) .def("__call__", &subtotal_transactions::operator()); ; class_< interval_transactions, bases > ("IntervalTransactions", init >() [with_custodian_and_ward<1, 2>()]) .def(init >() [with_custodian_and_ward<1, 2>()]) .def("flush", &xact_handler_t::flush) .def("__call__", &interval_transactions::operator()); ; class_< by_payee_transactions, bases > ("ByPayeeTransactions", init() [with_custodian_and_ward<1, 2>()]) .def("flush", &by_payee_transactions::flush) .def("__call__", &by_payee_transactions::operator()); ; class_< set_comm_as_payee, bases > ("SetCommAsPayee", init() [with_custodian_and_ward<1, 2>()]) .def("flush", &xact_handler_t::flush) .def("__call__", &xact_handler_t::operator()); ; class_< dow_transactions, bases > ("DowTransactions", init() [with_custodian_and_ward<1, 2>()]) .def("flush", &dow_transactions::flush) .def("__call__", &dow_transactions::operator()); ; scope().attr("BUDGET_BUDGETED") = BUDGET_BUDGETED; scope().attr("BUDGET_UNBUDGETED") = BUDGET_UNBUDGETED; class_< generate_transactions, bases > ("GenerateTransactions", init() [with_custodian_and_ward<1, 2>()]) .def("add_transaction", &generate_transactions::add_transaction) .def("add_period_entries", py_add_period_entries) .def("flush", &xact_handler_t::flush) .def("__call__", &xact_handler_t::operator()); ; class_< budget_transactions, bases > ("BudgetTransactions", init() [with_custodian_and_ward<1, 2>()]) .def("add_transaction", &generate_transactions::add_transaction) .def("add_period_entries", py_add_period_entries) .def("flush", &budget_transactions::flush) .def("__call__", &xact_handler_t::operator()); ; class_< forecast_transactions, bases > ("ForecastTransactions", init() [with_custodian_and_ward<1, 2>()]) .def("add_transaction", &forecast_transactions::add_transaction) .def("add_period_entries", py_add_period_entries) .def("flush", &forecast_transactions::flush) .def("__call__", &xact_handler_t::operator()); ; def("walk_entries", py_walk_entries); def("walk_transactions", py_walk_transactions); typedef item_handler account_handler_t; scope().attr("ACCOUNT_TO_DISPLAY") = ACCOUNT_TO_DISPLAY; scope().attr("ACCOUNT_DISPLAYED") = ACCOUNT_DISPLAYED; scope().attr("ACCOUNT_SORT_CALC") = ACCOUNT_SORT_CALC; class_< account_xdata_t > ("AccountXData") .def_readwrite("value", &account_xdata_t::value) .def_readwrite("total", &account_xdata_t::total) .def_readwrite("sort_value", &account_xdata_t::sort_value) .def_readwrite("count", &account_xdata_t::count) .def_readwrite("total_count", &account_xdata_t::total_count) .def_readwrite("virtuals", &account_xdata_t::virtuals) .def_readwrite("dflags", &account_xdata_t::dflags) ; def("account_has_xdata", account_has_xdata); def("account_xdata", account_xdata, return_internal_reference<1>()); def("clear_accounts_xdata", clear_accounts_xdata); def("clear_all_xdata", clear_all_xdata); class_< account_handler_t, item_handler_wrap > ("AccountHandler") .def(init()[with_custodian_and_ward<1, 2>()]) .def("flush", &account_handler_t::flush, &item_handler_wrap::default_flush) .def("__call__", &account_handler_t::operator(), &item_handler_wrap::default_call) ; def("sum_accounts", sum_accounts); def("walk_accounts", py_walk_accounts_1); def("walk_accounts", py_walk_accounts_2); def("walk_accounts", py_walk_accounts_3); def("walk_commodities", py_walk_commodities); } #endif // USE_BOOST_PYTHON