diff options
author | John Wiegley <johnw@newartisans.com> | 2008-08-05 13:17:04 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2008-08-05 18:05:49 -0400 |
commit | f6f4a46cf5b14f9a2170cd6475958efbf320caec (patch) | |
tree | 05bc1defcdebc201de3dd10477483d906a842821 /filters.cc | |
parent | b7970b29855563e4c67f85af8b31233eda80c22a (diff) | |
download | fork-ledger-f6f4a46cf5b14f9a2170cd6475958efbf320caec.tar.gz fork-ledger-f6f4a46cf5b14f9a2170cd6475958efbf320caec.tar.bz2 fork-ledger-f6f4a46cf5b14f9a2170cd6475958efbf320caec.zip |
Moved around most of the files so that source code is in src/, documentation
is in doc/, etc.
Diffstat (limited to 'filters.cc')
-rw-r--r-- | filters.cc | 755 |
1 files changed, 0 insertions, 755 deletions
diff --git a/filters.cc b/filters.cc deleted file mode 100644 index e5455423..00000000 --- a/filters.cc +++ /dev/null @@ -1,755 +0,0 @@ -/* - * Copyright (c) 2003-2008, John Wiegley. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of New Artisans LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "filters.h" -#include "iterators.h" -#include "compare.h" -#include "session.h" -#include "format.h" -#include "textual.h" - -namespace ledger { - -pass_down_xacts::pass_down_xacts(xact_handler_ptr handler, - xacts_iterator& iter) - : item_handler<xact_t>(handler) -{ - TRACE_CTOR(pass_down_xacts, "xact_handler_ptr, xacts_iterator"); - - for (xact_t * xact = iter(); xact; xact = iter()) - item_handler<xact_t>::operator()(*xact); -} - -void truncate_entries::flush() -{ - if (! xacts.size()) - return; - - entry_t * last_entry = (*xacts.begin())->entry; - - int l = 0; - foreach (xact_t * xact, xacts) - if (last_entry != xact->entry) { - l++; - last_entry = xact->entry; - } - l++; - - last_entry = (*xacts.begin())->entry; - - int i = 0; - foreach (xact_t * xact, xacts) { - if (last_entry != xact->entry) { - last_entry = xact->entry; - i++; - } - - bool print = false; - if (head_count) { - if (head_count > 0 && i < head_count) - print = true; - else if (head_count < 0 && i >= - head_count) - print = true; - } - - if (! print && tail_count) { - if (tail_count > 0 && l - i <= tail_count) - print = true; - else if (tail_count < 0 && l - i > - tail_count) - print = true; - } - - if (print) - item_handler<xact_t>::operator()(*xact); - } - xacts.clear(); - - item_handler<xact_t>::flush(); -} - -void set_account_value::operator()(xact_t& xact) -{ - account_t * acct = xact.reported_account(); - - account_t::xdata_t& xdata(acct->xdata()); - xact.add_to_value(xdata.value); - - xdata.count++; - if (xact.has_flags(XACT_VIRTUAL)) - xdata.virtuals++; - - item_handler<xact_t>::operator()(xact); -} - -void sort_xacts::post_accumulated_xacts() -{ - std::stable_sort(xacts.begin(), xacts.end(), - compare_items<xact_t>(sort_order)); - - foreach (xact_t * xact, xacts) { - xact->xdata().drop_flags(XACT_EXT_SORT_CALC); - item_handler<xact_t>::operator()(*xact); - } - - xacts.clear(); -} - -void calc_xacts::operator()(xact_t& xact) -{ - try { - xact_t::xdata_t& xdata(xact.xdata()); - - if (last_xact && last_xact->has_xdata()) { - if (xdata.total.is_null()) - xdata.total = last_xact->xdata().total; - else - xdata.total += last_xact->xdata().total; - xdata.index = last_xact->xdata().index + 1; - } else { - xdata.index = 0; - } - - if (! xdata.has_flags(XACT_EXT_NO_TOTAL)) - xact.add_to_value(xdata.total); - - item_handler<xact_t>::operator()(xact); - - last_xact = &xact; - } - catch (const std::exception& err) { - add_error_context("Calculating transaction at"); -#if 0 - add_error_context(xact_context(xact)); -#endif - throw err; - } -} - -void invert_xacts::operator()(xact_t& xact) -{ - if (xact.has_xdata() && - xact.xdata().has_flags(XACT_EXT_COMPOUND)) { - xact.xdata().value.negate(); - } else { - xact.amount.negate(); - if (xact.cost) - xact.cost->negate(); - } - - item_handler<xact_t>::operator()(xact); -} - - -static inline -void handle_value(const value_t& value, - account_t * account, - entry_t * entry, - unsigned int flags, - std::list<xact_t>& temps, - item_handler<xact_t>& handler, - const date_t& date = date_t(), - xacts_list * component_xacts = NULL) -{ - temps.push_back(xact_t(account)); - xact_t& xact(temps.back()); - xact.entry = entry; - xact.add_flags(XACT_TEMP); - entry->add_xact(&xact); - - // If there are component xacts to associate with this - // temporary, do so now. - - if (component_xacts) - xact.xdata().copy_component_xacts(*component_xacts); - - // If the account for this xact is all virtual, then report - // the xact as such. This allows subtotal reports to show - // "(Account)" for accounts that contain only virtual xacts. - - if (account && account->has_xdata()) - if (! account->xdata().has_flags(ACCOUNT_EXT_HAS_NON_VIRTUALS)) { - xact.add_flags(XACT_VIRTUAL); - if (! account->xdata().has_flags(ACCOUNT_EXT_HAS_UNB_VIRTUALS)) - xact.add_flags(XACT_BALANCE); - } - - xact_t::xdata_t& xdata(xact.xdata()); - - if (is_valid(date)) - xdata.date = date; - - value_t temp(value); - - switch (value.type()) { - case value_t::BOOLEAN: - case value_t::DATETIME: - case value_t::DATE: - case value_t::INTEGER: - temp.cast(value_t::AMOUNT); - // fall through... - - case value_t::AMOUNT: - xact.amount = temp.as_amount(); - break; - - case value_t::BALANCE: - case value_t::BALANCE_PAIR: - xdata.value = temp; - flags |= XACT_EXT_COMPOUND; - break; - - default: - assert(false); // jww (2008-04-24): What to do here? - break; - } - - if (flags) - xdata.add_flags(flags); - - handler(xact); -} - -void collapse_xacts::report_subtotal() -{ - assert(count >= 1); - - if (count == 1) { - item_handler<xact_t>::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_xacts::operator()(xact_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(); - - xact.add_to_value(subtotal); - count++; - - last_entry = xact.entry; - last_xact = &xact; -} - -void related_xacts::flush() -{ - if (xacts.size() > 0) { - foreach (xact_t * xact, xacts) { - if (xact->entry) { - foreach (xact_t * r_xact, xact->entry->xacts) { - xact_t::xdata_t& xdata(r_xact->xdata()); - if (! xdata.has_flags(XACT_EXT_HANDLED) && - (! xdata.has_flags(XACT_EXT_RECEIVED) ? - ! r_xact->has_flags(XACT_AUTO | XACT_VIRTUAL) : - also_matching)) { - xdata.add_flags(XACT_EXT_HANDLED); - item_handler<xact_t>::operator()(*r_xact); - } - } - } else { - // This code should only be reachable from the "output" - // command, since that is the only command which attempts to - // output auto or period entries. - xact_t::xdata_t& xdata(xact->xdata()); - if (! xdata.has_flags(XACT_EXT_HANDLED) && - ! xact->has_flags(XACT_AUTO)) { - xdata.add_flags(XACT_EXT_HANDLED); - item_handler<xact_t>::operator()(*xact); - } - } - } - } - - item_handler<xact_t>::flush(); -} - -void changed_value_xacts::output_diff(const date_t& date) -{ - value_t cur_bal; - - last_xact->xdata().date = date; -#if 0 - compute_total(cur_bal, details_t(*last_xact)); -#endif - cur_bal.round(); - -#if 0 - // jww (2008-04-24): What does this do? - last_xact->xdata().date = 0; -#endif - - 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 = date; - - handle_value(diff, NULL, &entry, XACT_EXT_NO_TOTAL, xact_temps, - *handler); - } -} - -void changed_value_xacts::operator()(xact_t& xact) -{ - if (last_xact) - output_diff(last_xact->reported_date()); - - if (changed_values_only) - xact.xdata().add_flags(XACT_EXT_DISPLAYED); - - item_handler<xact_t>::operator()(xact); - -#if 0 - compute_total(last_balance, details_t(xact)); -#endif - last_balance.round(); - - last_xact = &xact; -} - -void component_xacts::operator()(xact_t& xact) -{ - if (handler && pred(xact)) { - if (xact.has_xdata() && - xact.xdata().has_component_xacts()) -#if 0 - xact.xdata().walk_component_xacts(*handler); -#else - ; -#endif - else - (*handler)(xact); - } -} - -void subtotal_xacts::report_subtotal(const char * spec_fmt) -{ - std::ostringstream out_date; - if (! spec_fmt) { - string fmt = "- "; - fmt += output_date_format; - out_date << format_date(finish, string(fmt)); - } else { - out_date << format_date(finish, string(spec_fmt)); - } - - entry_temps.push_back(entry_t()); - entry_t& entry = entry_temps.back(); - entry.payee = out_date.str(); - entry._date = start; - - foreach (values_map::value_type& pair, values) - handle_value(pair.second.value, pair.second.account, &entry, 0, - xact_temps, *handler, finish, &pair.second.components); - - values.clear(); -} - -void subtotal_xacts::operator()(xact_t& xact) -{ - if (! is_valid(start) || xact.date() < start) - start = xact.date(); - if (! is_valid(finish) || xact.date() > finish) - finish = xact.date(); - - account_t * acct = xact.reported_account(); - assert(acct); - - values_map::iterator i = values.find(acct->fullname()); - if (i == values.end()) { - value_t temp; - xact.add_to_value(temp); - std::pair<values_map::iterator, bool> result - = values.insert(values_pair(acct->fullname(), acct_value_t(acct, temp))); - assert(result.second); - - if (remember_components) - (*result.first).second.components.push_back(&xact); - } else { - xact.add_to_value((*i).second.value); - - if (remember_components) - (*i).second.components.push_back(&xact); - } - - // If the account for this xact is all virtual, mark it as - // such, so that `handle_value' can show "(Account)" for accounts - // that contain only virtual xacts. - - if (! xact.has_flags(XACT_VIRTUAL)) - xact.reported_account()->xdata().add_flags(ACCOUNT_EXT_HAS_NON_VIRTUALS); - else if (! xact.has_flags(XACT_BALANCE)) - xact.reported_account()->xdata().add_flags(ACCOUNT_EXT_HAS_UNB_VIRTUALS); -} - -void interval_xacts::report_subtotal(const date_t& date) -{ - assert(last_xact); - - start = interval.begin; - if (is_valid(date)) - finish = date - gregorian::days(1); - else - finish = last_xact->date(); - - subtotal_xacts::report_subtotal(); - - last_xact = NULL; -} - -void interval_xacts::operator()(xact_t& xact) -{ - const date_t& date(xact.date()); - - if ((is_valid(interval.begin) && date < interval.begin) || - (is_valid(interval.end) && date >= interval.end)) - return; - - if (interval) { - if (! started) { - if (! is_valid(interval.begin)) - interval.start(date); - start = interval.begin; - started = true; - } - - date_t quant = interval.increment(interval.begin); - if (date >= quant) { - if (last_xact) - report_subtotal(quant); - - date_t temp; - while (date >= (temp = interval.increment(quant))) { - if (quant == temp) - break; - quant = temp; - } - start = interval.begin = quant; - } - - subtotal_xacts::operator()(xact); - } else { - item_handler<xact_t>::operator()(xact); - } - - last_xact = &xact; -} - -by_payee_xacts::~by_payee_xacts() -{ - TRACE_DTOR(by_payee_xacts); - - foreach (payee_subtotals_map::value_type& pair, payee_subtotals) - checked_delete(pair.second); -} - -void by_payee_xacts::flush() -{ - foreach (payee_subtotals_map::value_type& pair, payee_subtotals) - pair.second->report_subtotal(pair.first.c_str()); - - item_handler<xact_t>::flush(); - - payee_subtotals.clear(); -} - -void by_payee_xacts::operator()(xact_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_xacts(handler, remember_components)); - std::pair<payee_subtotals_map::iterator, bool> result - = payee_subtotals.insert(temp); - - assert(result.second); - if (! result.second) - return; - i = result.first; - } - - if (xact.date() > (*i).second->start) - (*i).second->start = xact.date(); - - (*(*i).second)(xact); -} - -void set_comm_as_payee::operator()(xact_t& xact) -{ - entry_temps.push_back(*xact.entry); - entry_t& entry = entry_temps.back(); - entry._date = xact.date(); - entry.code = xact.entry->code; - - if (xact.amount.commodity()) - entry.payee = xact.amount.commodity().symbol(); - else - entry.payee = "<none>"; - - xact_temps.push_back(xact); - xact_t& temp = xact_temps.back(); - temp.entry = &entry; - temp.state = xact.state; - temp.add_flags(XACT_TEMP); - - entry.add_xact(&temp); - - item_handler<xact_t>::operator()(temp); -} - -void set_code_as_payee::operator()(xact_t& xact) -{ - entry_temps.push_back(*xact.entry); - entry_t& entry = entry_temps.back(); - entry._date = xact.date(); - - if (xact.entry->code) - entry.payee = *xact.entry->code; - else - entry.payee = "<none>"; - - xact_temps.push_back(xact); - xact_t& temp = xact_temps.back(); - temp.entry = &entry; - temp.state = xact.state; - temp.add_flags(XACT_TEMP); - - entry.add_xact(&temp); - - item_handler<xact_t>::operator()(temp); -} - -void dow_xacts::flush() -{ - for (int i = 0; i < 7; i++) { - start = finish = date_t(); - foreach (xact_t * xact, days_of_the_week[i]) - subtotal_xacts::operator()(*xact); - subtotal_xacts::report_subtotal("%As"); - days_of_the_week[i].clear(); - } - - subtotal_xacts::flush(); -} - -void generate_xacts::add_period_entries - (period_entries_list& period_entries) -{ - foreach (period_entry_t * entry, period_entries) - foreach (xact_t * xact, entry->xacts) - add_xact(entry->period, *xact); -} - -void generate_xacts::add_xact(const interval_t& period, - xact_t& xact) -{ - pending_xacts.push_back(pending_xacts_pair(period, &xact)); -} - -void budget_xacts::report_budget_items(const date_t& date) -{ - if (pending_xacts.size() == 0) - return; - - bool reported; - do { - reported = false; - foreach (pending_xacts_list::value_type& pair, pending_xacts) { - date_t& begin = pair.first.begin; - if (! is_valid(begin)) { - pair.first.start(date); - begin = pair.first.begin; - } - - if (begin < date && - (! is_valid(pair.first.end) || begin < pair.first.end)) { - xact_t& xact = *pair.second; - - DEBUG("ledger.walk.budget", "Reporting budget for " - << xact.reported_account()->fullname()); - - entry_temps.push_back(entry_t()); - entry_t& entry = entry_temps.back(); - entry.payee = "Budget entry"; - entry._date = begin; - - xact_temps.push_back(xact); - xact_t& temp = xact_temps.back(); - temp.entry = &entry; - temp.add_flags(XACT_AUTO | XACT_TEMP); - temp.amount.negate(); - entry.add_xact(&temp); - - begin = pair.first.increment(begin); - - item_handler<xact_t>::operator()(temp); - - reported = true; - } - } - } while (reported); -} - -void budget_xacts::operator()(xact_t& xact) -{ - bool xact_in_budget = false; - - foreach (pending_xacts_list::value_type& pair, pending_xacts) - for (account_t * acct = xact.reported_account(); - acct; - acct = acct->parent) { - if (acct == (*pair.second).reported_account()) { - xact_in_budget = true; - // Report the xact as if it had occurred in the parent - // account. - if (xact.reported_account() != acct) - xact.xdata().account = acct; - goto handle; - } - } - - handle: - if (xact_in_budget && flags & BUDGET_BUDGETED) { - report_budget_items(xact.date()); - item_handler<xact_t>::operator()(xact); - } - else if (! xact_in_budget && flags & BUDGET_UNBUDGETED) { - item_handler<xact_t>::operator()(xact); - } -} - -void forecast_xacts::add_xact(const interval_t& period, xact_t& xact) -{ - generate_xacts::add_xact(period, xact); - - interval_t& i = pending_xacts.back().first; - if (! is_valid(i.begin)) { - i.start(current_date); - i.begin = i.increment(i.begin); - } else { - while (i.begin < current_date) - i.begin = i.increment(i.begin); - } -} - -void forecast_xacts::flush() -{ - xacts_list passed; - date_t last; - - 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 ((*i).first.begin < (*least).first.begin) - least = i; - - date_t& begin = (*least).first.begin; - - if (is_valid((*least).first.end) && begin >= (*least).first.end) { - pending_xacts.erase(least); - passed.remove((*least).second); - continue; - } - - xact_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); - xact_t& temp = xact_temps.back(); - temp.entry = &entry; - temp.add_flags(XACT_AUTO | XACT_TEMP); - entry.add_xact(&temp); - - date_t next = (*least).first.increment(begin); - if (next < begin || (is_valid(last) && (next - last).days() > 365 * 5)) - break; - begin = next; - - item_handler<xact_t>::operator()(temp); - - if (temp.has_xdata() && - temp.xdata().has_flags(XACT_EXT_MATCHES)) { - if (! pred(temp)) - break; - last = temp.date(); - passed.clear(); - } else { - bool found = false; - foreach (xact_t * x, passed) - if (x == &xact) { - found = true; - break; - } - - if (! found) { - passed.push_back(&xact); - if (passed.size() >= pending_xacts.size()) - break; - } - } - } - - item_handler<xact_t>::flush(); -} - -pass_down_accounts::pass_down_accounts(acct_handler_ptr handler, - accounts_iterator& iter) - : item_handler<account_t>(handler) -{ - TRACE_CTOR(pass_down_accounts, - "acct_handler_ptr, accounts_iterator"); - for (account_t * account = iter(); account; account = iter()) - item_handler<account_t>::operator()(*account); -} - -} // namespace ledger |