ledger/walk.cc

245 lines
5.3 KiB
C++

#include "walk.h"
#include "format.h"
namespace ledger {
void sort_transactions::flush()
{
std::stable_sort(transactions.begin(), transactions.end(),
compare_items<transaction_t>(sort_order));
for (transactions_deque::iterator i = transactions.begin();
i != transactions.end();
i++)
(*handler)(*i);
transactions.clear();
item_handler<transaction_t>::flush();
}
void calc_transactions::operator()(transaction_t * xact)
{
if (last_xact) {
xact->total += last_xact->total;
xact->index = last_xact->index + 1;
} else {
xact->index = 0;
}
if (inverted) {
xact->amount.negate();
if (xact->cost)
xact->cost->negate();
}
if (! (xact->dflags & TRANSACTION_NO_TOTAL))
xact->total += *xact;
(*handler)(xact);
if (inverted) {
xact->amount.negate();
if (xact->cost)
xact->cost->negate();
}
last_xact = xact;
}
void collapse_transactions::report_cumulative_subtotal()
{
if (count == 1) {
(*handler)(last_xact);
} else {
assert(count > 1);
totals_account->total = subtotal;
value_t result;
format_t::compute_total(result, details_t(totals_account));
#if 0
for (amounts_map::const_iterator i = result.amounts.begin();
i != result.amounts.end();
i++) {
transaction_t * total_xact = new transaction_t(totals_account);
xact_temps.push_back(total_xact);
total_xact->entry = last_entry;
total_xact->amount = (*i).second;
(*handler)(total_xact);
}
#endif
}
subtotal = 0;
count = 0;
}
void changed_value_transactions::operator()(transaction_t * xact)
{
if (last_xact) {
value_t prev_bal;
value_t cur_bal;
std::time_t current = xact ? xact->entry->date : std::time(NULL);
std::time_t prev_date = last_xact->entry->date;
format_t::compute_total(prev_bal, details_t(last_xact));
last_xact->entry->date = current;
format_t::compute_total(cur_bal, details_t(last_xact));
last_xact->entry->date = prev_date;
cur_bal -= prev_bal;
if (cur_bal) {
entry_t * entry = new entry_t;
entry_temps.push_back(entry);
entry->payee = "Commodities revalued";
entry->date = current;
#if 0
for (amounts_map::const_iterator i = diff.amounts.begin();
i != diff.amounts.end();
i++) {
transaction_t * temp_xact = new transaction_t(NULL);
xact_temps.push_back(temp_xact);
temp_xact->entry = entry;
temp_xact->amount = (*i).second;
temp_xact->dflags |= TRANSACTION_NO_TOTAL;
(*handler)(temp_xact);
}
#endif
}
}
if (xact) {
if (changed_values_only)
xact->dflags |= TRANSACTION_DISPLAYED;
(*handler)(xact);
}
last_xact = xact;
}
void subtotal_transactions::flush(const char * spec_fmt)
{
char buf[256];
if (! spec_fmt) {
std::string fmt = "- ";
fmt += format_t::date_format;
// Make sure the end date is inclusive
if (start != finish)
finish -= 86400;
std::strftime(buf, 255, fmt.c_str(), std::localtime(&finish));
} else {
std::strftime(buf, 255, spec_fmt, std::localtime(&finish));
}
entry_t * entry = new entry_t;
entry_temps.push_back(entry);
entry->payee = buf;
for (balances_map::iterator i = balances.begin();
i != balances.end();
i++) {
entry->date = finish;
transaction_t temp((*i).first);
temp.entry = entry;
temp.total = (*i).second;
value_t result;
format_t::compute_total(result, details_t(&temp));
entry->date = start;
#if 0
for (amounts_map::const_iterator j = result.amounts.begin();
j != result.amounts.end();
j++) {
transaction_t * xact = new transaction_t((*i).first);
xact_temps.push_back(xact);
xact->entry = entry;
xact->amount = (*j).second;
(*handler)(xact);
}
#endif
}
balances.clear();
item_handler<transaction_t>::flush();
}
void subtotal_transactions::operator()(transaction_t * xact)
{
if (balances.size() == 0) {
start = finish = xact->entry->date;
} else {
if (std::difftime(xact->entry->date, start) < 0)
start = xact->entry->date;
if (std::difftime(xact->entry->date, finish) > 0)
finish = xact->entry->date;
}
balances_map::iterator i = balances.find(xact->account);
if (i == balances.end())
balances.insert(balances_pair(xact->account, *xact));
else
(*i).second += *xact;
}
void interval_transactions::operator()(transaction_t * xact)
{
std::time_t quant = interval.increment(begin);
if (std::difftime(xact->entry->date, quant) > 0) {
if (last_xact) {
start = begin;
finish = quant;
flush();
}
if (! interval.seconds) {
struct std::tm * desc = std::localtime(&xact->entry->date);
if (interval.years)
desc->tm_mon = 0;
desc->tm_mday = 1;
desc->tm_hour = 0;
desc->tm_min = 0;
desc->tm_sec = 0;
quant = std::mktime(desc);
}
std::time_t temp;
while (std::difftime(xact->entry->date,
temp = interval.increment(quant)) > 0)
quant = temp;
begin = quant;
}
subtotal_transactions::operator()(xact);
last_xact = xact;
}
void dow_transactions::flush()
{
for (int i = 0; i < 7; i++) {
for (transactions_deque::iterator d = days_of_the_week[i].begin();
d != days_of_the_week[i].end();
d++)
subtotal_transactions::operator()(*d);
subtotal_transactions::flush("%As");
days_of_the_week[i].clear();
}
}
} // namespace ledger