only compute the cost when it differs from the amount

This commit is contained in:
John Wiegley 2004-08-21 15:55:03 -04:00
parent 225acd14e5
commit 000bfe1cec
18 changed files with 227 additions and 112 deletions

View file

@ -890,8 +890,8 @@ void amount_t::write_quantity(std::ostream& out) const
out.write(&byte, sizeof(byte)); out.write(&byte, sizeof(byte));
std::size_t size; std::size_t size;
mpz_export(buf, &size, 1, sizeof(int), 0, 0, MPZ(quantity)); mpz_export(buf, &size, 1, sizeof(short), 0, 0, MPZ(quantity));
unsigned short len = size * sizeof(int); unsigned short len = size * sizeof(short);
out.write((char *)&len, sizeof(len)); out.write((char *)&len, sizeof(len));
if (len) { if (len) {
@ -930,7 +930,7 @@ void amount_t::read_quantity(std::istream& in)
unsigned short len; unsigned short len;
in.read((char *)&len, sizeof(len)); in.read((char *)&len, sizeof(len));
in.read(buf, len); in.read(buf, len);
mpz_import(MPZ(quantity), len / sizeof(int), 1, sizeof(int), 0, 0, buf); mpz_import(MPZ(quantity), len / sizeof(short), 1, sizeof(short), 0, 0, buf);
char negative; char negative;
in.read(&negative, sizeof(negative)); in.read(&negative, sizeof(negative));

View file

@ -21,7 +21,7 @@ void automated_transaction_t::extend_entry(entry_t * entry)
amt = (*t)->amount; amt = (*t)->amount;
transaction_t * xact transaction_t * xact
= new transaction_t((*t)->account, amt, amt, = new transaction_t((*t)->account, amt,
(*t)->flags | TRANSACTION_AUTO); (*t)->flags | TRANSACTION_AUTO);
entry->add_transaction(xact); entry->add_transaction(xact);
} }

View file

@ -85,19 +85,35 @@ void balance_t::write(std::ostream& out,
} }
balance_pair_t::balance_pair_t(const transaction_t& xact) balance_pair_t::balance_pair_t(const transaction_t& xact)
: quantity(xact.amount), cost(xact.cost) {} : quantity(xact.amount), cost(NULL)
{
if (xact.cost)
cost = new balance_t(*xact.cost);
}
balance_pair_t& balance_pair_t::operator+=(const transaction_t& xact) balance_pair_t& balance_pair_t::operator+=(const transaction_t& xact)
{ {
if (xact.cost && ! cost)
cost = new balance_t(quantity);
quantity += xact.amount; quantity += xact.amount;
cost += xact.cost;
if (cost)
*cost += xact.cost ? *xact.cost : xact.amount;
return *this; return *this;
} }
balance_pair_t& balance_pair_t::operator-=(const transaction_t& xact) balance_pair_t& balance_pair_t::operator-=(const transaction_t& xact)
{ {
if (xact.cost && ! cost)
cost = new balance_t(quantity);
quantity -= xact.amount; quantity -= xact.amount;
cost -= xact.cost;
if (cost)
*cost -= xact.cost ? *xact.cost : xact.amount;
return *this; return *this;
} }

133
balance.h
View file

@ -387,93 +387,146 @@ class balance_pair_t
{ {
public: public:
balance_t quantity; balance_t quantity;
balance_t cost; balance_t * cost;
bool valid() const { bool valid() const {
return quantity.valid() && cost.valid(); return quantity.valid() && (! cost || cost->valid());
} }
// constructors // constructors
balance_pair_t() {} balance_pair_t() : cost(NULL) {}
balance_pair_t(const balance_pair_t& bal_pair) balance_pair_t(const balance_pair_t& bal_pair)
: quantity(bal_pair.quantity), cost(bal_pair.cost) {} : quantity(bal_pair.quantity), cost(NULL) {
if (bal_pair.cost)
cost = new balance_t(*bal_pair.cost);
}
#if 0
balance_pair_t(const balance_t& _quantity, const balance_t& _cost) balance_pair_t(const balance_t& _quantity, const balance_t& _cost)
: quantity(_quantity), cost(_cost) {} : quantity(_quantity), cost(_cost) {}
#endif
balance_pair_t(const balance_t& _quantity) balance_pair_t(const balance_t& _quantity)
: quantity(_quantity), cost(_quantity) {} : quantity(_quantity), cost(NULL) {}
#if 0
balance_pair_t(const amount_t& _quantity, const amount_t& _cost) balance_pair_t(const amount_t& _quantity, const amount_t& _cost)
: quantity(_quantity), cost(_cost) {} : quantity(_quantity), cost(_cost) {}
#endif
balance_pair_t(const amount_t& _quantity) balance_pair_t(const amount_t& _quantity)
: quantity(_quantity), cost(_quantity) {} : quantity(_quantity), cost(NULL) {}
balance_pair_t(const int value) balance_pair_t(const int value)
: quantity(value), cost(value) {} : quantity(value), cost(NULL) {}
balance_pair_t(const unsigned int value) balance_pair_t(const unsigned int value)
: quantity(value), cost(value) {} : quantity(value), cost(NULL) {}
balance_pair_t(const double value) balance_pair_t(const double value)
: quantity(value), cost(value) {} : quantity(value), cost(NULL) {}
balance_pair_t(const transaction_t& xact); balance_pair_t(const transaction_t& xact);
// destructor // destructor
~balance_pair_t() {} ~balance_pair_t() {
if (cost)
delete cost;
}
// assignment operator // assignment operator
balance_pair_t& operator=(const balance_pair_t& bal_pair) { balance_pair_t& operator=(const balance_pair_t& bal_pair) {
if (cost) {
delete cost;
cost = NULL;
}
quantity = bal_pair.quantity; quantity = bal_pair.quantity;
cost = bal_pair.cost; if (bal_pair.cost)
cost = new balance_t(*bal_pair.cost);
return *this; return *this;
} }
balance_pair_t& operator=(const balance_t& bal) { balance_pair_t& operator=(const balance_t& bal) {
quantity = cost = bal; if (cost) {
delete cost;
cost = NULL;
}
quantity = bal;
return *this; return *this;
} }
balance_pair_t& operator=(const amount_t& amt) { balance_pair_t& operator=(const amount_t& amt) {
quantity = cost = amt; if (cost) {
delete cost;
cost = NULL;
}
quantity = amt;
return *this; return *this;
} }
balance_pair_t& operator=(const int value) { balance_pair_t& operator=(const int value) {
quantity = cost = amount_t(value); if (cost) {
delete cost;
cost = NULL;
}
quantity = value;
return *this; return *this;
} }
balance_pair_t& operator=(const unsigned int value) { balance_pair_t& operator=(const unsigned int value) {
quantity = cost = amount_t(value); if (cost) {
delete cost;
cost = NULL;
}
quantity = value;
return *this; return *this;
} }
balance_pair_t& operator=(const double value) { balance_pair_t& operator=(const double value) {
quantity = cost = amount_t(value); if (cost) {
delete cost;
cost = NULL;
}
quantity = value;
return *this; return *this;
} }
// in-place arithmetic // in-place arithmetic
balance_pair_t& operator+=(const balance_pair_t& bal_pair) { balance_pair_t& operator+=(const balance_pair_t& bal_pair) {
if (bal_pair.cost && ! cost)
cost = new balance_t(quantity);
quantity += bal_pair.quantity; quantity += bal_pair.quantity;
cost += bal_pair.cost;
if (cost)
*cost += bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
return *this; return *this;
} }
balance_pair_t& operator+=(const balance_t& bal) { balance_pair_t& operator+=(const balance_t& bal) {
quantity += bal; quantity += bal;
cost += bal; if (cost)
*cost += bal;
return *this; return *this;
} }
balance_pair_t& operator+=(const amount_t& amt) { balance_pair_t& operator+=(const amount_t& amt) {
quantity += amt; quantity += amt;
cost += amt; if (cost)
*cost += amt;
return *this; return *this;
} }
balance_pair_t& operator+=(const transaction_t& xact); balance_pair_t& operator+=(const transaction_t& xact);
balance_pair_t& operator-=(const balance_pair_t& bal_pair) { balance_pair_t& operator-=(const balance_pair_t& bal_pair) {
if (bal_pair.cost && ! cost)
cost = new balance_t(quantity);
quantity -= bal_pair.quantity; quantity -= bal_pair.quantity;
cost -= bal_pair.cost;
if (cost)
*cost -= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
return *this; return *this;
} }
balance_pair_t& operator-=(const balance_t& bal) { balance_pair_t& operator-=(const balance_t& bal) {
quantity -= bal; quantity -= bal;
cost -= bal; if (cost)
*cost -= bal;
return *this; return *this;
} }
balance_pair_t& operator-=(const amount_t& amt) { balance_pair_t& operator-=(const amount_t& amt) {
quantity -= amt; quantity -= amt;
cost -= amt; if (cost)
*cost -= amt;
return *this; return *this;
} }
balance_pair_t& operator-=(const transaction_t& xact); balance_pair_t& operator-=(const transaction_t& xact);
@ -513,34 +566,50 @@ class balance_pair_t
// multiplication and division // multiplication and division
balance_pair_t& operator*=(const balance_pair_t& bal_pair) { balance_pair_t& operator*=(const balance_pair_t& bal_pair) {
if (bal_pair.cost && ! cost)
cost = new balance_t(quantity);
quantity *= bal_pair.quantity; quantity *= bal_pair.quantity;
cost *= bal_pair.quantity;
if (cost)
*cost *= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
return *this; return *this;
} }
balance_pair_t& operator*=(const balance_t& bal) { balance_pair_t& operator*=(const balance_t& bal) {
quantity *= bal; quantity *= bal;
cost *= bal; if (cost)
*cost *= bal;
return *this; return *this;
} }
balance_pair_t& operator*=(const amount_t& amt) { balance_pair_t& operator*=(const amount_t& amt) {
quantity *= amt; quantity *= amt;
cost *= amt; if (cost)
*cost *= amt;
return *this; return *this;
} }
balance_pair_t& operator/=(const balance_pair_t& bal_pair) { balance_pair_t& operator/=(const balance_pair_t& bal_pair) {
if (bal_pair.cost && ! cost)
cost = new balance_t(quantity);
quantity /= bal_pair.quantity; quantity /= bal_pair.quantity;
cost /= bal_pair.quantity;
if (cost)
*cost /= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
return *this; return *this;
} }
balance_pair_t& operator/=(const balance_t& bal) { balance_pair_t& operator/=(const balance_t& bal) {
quantity /= bal; quantity /= bal;
cost /= bal; if (cost)
*cost /= bal;
return *this; return *this;
} }
balance_pair_t& operator/=(const amount_t& amt) { balance_pair_t& operator/=(const amount_t& amt) {
quantity /= amt; quantity /= amt;
cost /= amt; if (cost)
*cost /= amt;
return *this; return *this;
} }
@ -637,7 +706,8 @@ class balance_pair_t
// unary negation // unary negation
balance_pair_t& negate() { balance_pair_t& negate() {
quantity.negate(); quantity.negate();
cost.negate(); if (cost)
cost->negate();
return *this; return *this;
} }
balance_pair_t negated() const { balance_pair_t negated() const {
@ -658,7 +728,10 @@ class balance_pair_t
inline balance_pair_t abs(const balance_pair_t& bal_pair) { inline balance_pair_t abs(const balance_pair_t& bal_pair) {
balance_pair_t temp; balance_pair_t temp;
temp.quantity = abs(bal_pair.quantity); temp.quantity = abs(bal_pair.quantity);
temp.cost = abs(bal_pair.cost); if (bal_pair.cost) {
temp.cost = new balance_t;
*temp.cost = abs(*bal_pair.cost);
}
return temp; return temp;
} }

View file

@ -9,7 +9,7 @@
namespace ledger { namespace ledger {
const unsigned long binary_magic_number = 0xFFEED765; const unsigned long binary_magic_number = 0xFFEED765;
static const unsigned long format_version = 0x0002000e; static const unsigned long format_version = 0x00020010;
bool binary_parser_t::test(std::istream& in) const bool binary_parser_t::test(std::istream& in) const
{ {
@ -102,7 +102,10 @@ transaction_t * read_binary_transaction(std::istream& in, entry_t * entry)
xact->account->add_transaction(xact); xact->account->add_transaction(xact);
read_binary_amount(in, xact->amount); read_binary_amount(in, xact->amount);
read_binary_amount(in, xact->cost); if (read_binary_number<char>(in) == 1) {
xact->cost = new amount_t;
read_binary_amount(in, *xact->cost);
}
read_binary_number(in, xact->flags); read_binary_number(in, xact->flags);
read_binary_string(in, xact->note); read_binary_string(in, xact->note);
@ -314,7 +317,12 @@ void write_binary_transaction(std::ostream& out, transaction_t * xact)
{ {
write_binary_number(out, xact->account->ident); write_binary_number(out, xact->account->ident);
write_binary_amount(out, xact->amount); write_binary_amount(out, xact->amount);
write_binary_amount(out, xact->cost); if (xact->cost) {
write_binary_number<char>(out, 1);
write_binary_amount(out, *xact->cost);
} else {
write_binary_number<char>(out, 0);
}
write_binary_number(out, xact->flags); write_binary_number(out, xact->flags);
write_binary_string(out, xact->note); write_binary_string(out, xact->note);
} }

View file

@ -180,7 +180,7 @@ OPT_BEGIN(end_date, "e:") {
OPT_BEGIN(current, "c") { OPT_BEGIN(current, "c") {
if (! config->predicate.empty()) if (! config->predicate.empty())
config->predicate += "&"; config->predicate += "&";
config->predicate += "d<=N"; config->predicate += "d<=m";
} OPT_END(current); } OPT_END(current);
OPT_BEGIN(cleared, "C") { OPT_BEGIN(cleared, "C") {
@ -346,7 +346,7 @@ OPT_BEGIN(trend, "X") {
OPT_BEGIN(weighted_trend, "Z") { OPT_BEGIN(weighted_trend, "Z") {
config->value_expr = "a"; config->value_expr = "a";
config->total_expr config->total_expr
= "MD(MO/(1+(((N-d)/(30*86400))<0?0:((N-d)/(30*86400)))))"; = "MD(MO/(1+(((m-d)/(30*86400))<0?0:((m-d)/(30*86400)))))";
} OPT_END(weighted_trend); } OPT_END(weighted_trend);
} // namespace ledger } // namespace ledger

View file

@ -289,8 +289,8 @@ void format_t::format_elements(std::ostream& out,
std::string disp; std::string disp;
bool use_disp = false; bool use_disp = false;
if (details.xact->amount != details.xact->cost) { if (details.xact->cost) {
amount_t unit_cost = details.xact->cost / details.xact->amount; amount_t unit_cost = *details.xact->cost / details.xact->amount;
std::ostringstream stream; std::ostringstream stream;
stream << details.xact->amount << " @ " << unit_cost; stream << details.xact->amount << " @ " << unit_cost;
disp = stream.str(); disp = stream.str();

View file

@ -240,7 +240,8 @@ static void dataHandler(void *userData, const char *s, int len)
curr_value = value; curr_value = value;
xact->amount = value; xact->amount = value;
xact->cost = curr_value; if (value != curr_value)
xact->cost = new amount_t(curr_value);
break; break;
} }

View file

@ -30,9 +30,10 @@ bool journal_t::add_entry(entry_t * entry)
i++) { i++) {
(*i)->account->add_transaction(*i); (*i)->account->add_transaction(*i);
if ((*i)->amount != (*i)->cost) { if ((*i)->cost) {
assert((*i)->amount.commodity); assert((*i)->cost->commodity);
(*i)->amount.commodity->add_price(entry->date, (*i)->cost / (*i)->amount); (*i)->amount.commodity->add_price(entry->date,
*(*i)->cost / (*i)->amount);
} }
} }
@ -98,17 +99,15 @@ entry_t * journal_t::derive_entry(strings_list::iterator i,
m_xact = matching->transactions.front(); m_xact = matching->transactions.front();
amount_t amt(*i++); amount_t amt(*i++);
first = xact = new transaction_t(m_xact->account, amt, amt); first = xact = new transaction_t(m_xact->account, amt);
added->add_transaction(xact); added->add_transaction(xact);
if (xact->amount.commodity->symbol.empty()) { if (xact->amount.commodity->symbol.empty())
xact->amount.commodity = m_xact->amount.commodity; xact->amount.commodity = m_xact->amount.commodity;
xact->cost.commodity = m_xact->amount.commodity;
}
m_xact = matching->transactions.back(); m_xact = matching->transactions.back();
xact = new transaction_t(m_xact->account, - first->amount, - first->amount); xact = new transaction_t(m_xact->account, - first->amount);
added->add_transaction(xact); added->add_transaction(xact);
if (i != end && std::string(*i++) == "-from" && i != end) if (i != end && std::string(*i++) == "-from" && i != end)
@ -149,7 +148,7 @@ entry_t * journal_t::derive_entry(strings_list::iterator i,
} }
amount_t amt(*i++); amount_t amt(*i++);
transaction_t * xact = new transaction_t(acct, amt, amt); transaction_t * xact = new transaction_t(acct, amt);
added->add_transaction(xact); added->add_transaction(xact);
if (! xact->amount.commodity) if (! xact->amount.commodity)

View file

@ -49,7 +49,7 @@ class transaction_t
entry_t * entry; entry_t * entry;
account_t * account; account_t * account;
amount_t amount; amount_t amount;
amount_t cost; amount_t * cost;
unsigned short flags; unsigned short flags;
std::string note; std::string note;
@ -58,16 +58,20 @@ class transaction_t
mutable unsigned short dflags; mutable unsigned short dflags;
transaction_t(account_t * _account) transaction_t(account_t * _account)
: entry(NULL), account(_account), flags(TRANSACTION_NORMAL), : entry(NULL), account(_account), cost(NULL),
index(0), dflags(0) {} flags(TRANSACTION_NORMAL), index(0), dflags(0) {}
transaction_t(account_t * _account, transaction_t(account_t * _account,
const amount_t& _amount, const amount_t& _amount,
const amount_t& _cost,
unsigned int _flags = TRANSACTION_NORMAL, unsigned int _flags = TRANSACTION_NORMAL,
const std::string& _note = "") const std::string& _note = "")
: entry(NULL), account(_account), amount(_amount), : entry(NULL), account(_account), amount(_amount),
cost(_cost), flags(_flags), note(_note), index(0), dflags(0) {} cost(NULL), flags(_flags), note(_note), index(0), dflags(0) {}
~transaction_t() {
if (cost)
delete cost;
}
}; };
@ -127,18 +131,19 @@ class account_t
mutable balance_pair_t value; mutable balance_pair_t value;
mutable balance_pair_t total; mutable balance_pair_t total;
mutable unsigned int count; // transactions counted toward total mutable unsigned int count; // transactions counted toward total
mutable unsigned int subcount;
mutable ident_t ident; mutable ident_t ident;
mutable unsigned short dflags; mutable unsigned short dflags;
mutable std::string _fullname; mutable std::string _fullname;
static ident_t next_ident; static ident_t next_ident;
account_t(account_t * _parent, account_t(account_t * _parent,
const std::string& _name = "", const std::string& _name = "",
const std::string& _note = "") const std::string& _note = "")
: parent(_parent), name(_name), note(_note), : parent(_parent), name(_name), note(_note),
depth(parent ? parent->depth + 1 : 0), depth(parent ? parent->depth + 1 : 0),
count(0), dflags(0) {} count(0), subcount(0), dflags(0) {}
~account_t(); ~account_t();

View file

@ -490,8 +490,8 @@ register report, @samp{-T} changes the totals column; in a balance
report, this is the value given for each account. If @samp{-T} was report, this is the value given for each account. If @samp{-T} was
not specified, the current report style's value expression is used. not specified, the current report style's value expression is used.
@item N @item m
This is always the present date. This is always the present moment/date.
@end table @end table
@subsubsection Transaction/account details @subsubsection Transaction/account details
@ -522,7 +522,7 @@ it's depth is one.
@item n @item n
The index of a transaction, or the count of transactions affecting an The index of a transaction, or the count of transactions affecting an
account (including children). account.
@item X @item X
1, if a transaction's entry has been cleared, 0 otherwise. 1, if a transaction's entry has been cleared, 0 otherwise.
@ -538,6 +538,10 @@ account (including children).
The total of all transactions seen so far, or the total of an account The total of all transactions seen so far, or the total of an account
and all its children. and all its children.
@item N
The total count of transactions affecting an account and all its
children.
@item C @item C
The total cost of all transactions seen so far; the total cost of an The total cost of all transactions seen so far; the total cost of an
account and all its children. account and all its children.

3
qif.cc
View file

@ -99,7 +99,6 @@ unsigned int qif_parser_t::parse(std::istream& in,
xact->amount.commodity = def_commodity; xact->amount.commodity = def_commodity;
if (c == '$') if (c == '$')
xact->amount.negate(); xact->amount.negate();
xact->cost = xact->amount;
break; break;
case 'C': case 'C':
@ -164,7 +163,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
misc = journal->find_account("Miscellaneous"); misc = journal->find_account("Miscellaneous");
transaction_t * nxact = new transaction_t(misc); transaction_t * nxact = new transaction_t(misc);
entry->add_transaction(nxact); entry->add_transaction(nxact);
nxact->amount = nxact->cost = - xact->amount; nxact->amount.negate();
} }
if (journal->add_entry(entry.release())) if (journal->add_entry(entry.release()))

View file

@ -1,16 +0,0 @@
#!/usr/bin/python
import sys
import re
print_total = 0
def clean(num):
return float(re.sub("(\s+|\$|,)","",num))
for line in sys.stdin:
print line[:10],
if print_total:
print clean(line[68:80])
else:
print clean(line[55:67])

View file

@ -73,15 +73,13 @@ transaction_t * parse_transaction_text(char * line, account_t * account,
char * price_str = std::strchr(cost_str, '@'); char * price_str = std::strchr(cost_str, '@');
if (price_str) { if (price_str) {
*price_str++ = '\0'; *price_str++ = '\0';
xact->cost.parse(price_str); xact->cost = new amount_t;
xact->cost->parse(price_str);
} }
xact->amount.parse(cost_str); xact->amount.parse(cost_str);
if (price_str) if (price_str)
xact->cost *= xact->amount; *xact->cost *= xact->amount;
else
xact->cost = xact->amount;
} }
if (*p == '[' || *p == '(') { if (*p == '[' || *p == '(') {
@ -99,8 +97,8 @@ transaction_t * parse_transaction_text(char * line, account_t * account,
if (! xact->amount.commodity) if (! xact->amount.commodity)
xact->amount.commodity = commodity_t::null_commodity; xact->amount.commodity = commodity_t::null_commodity;
if (! xact->cost.commodity) if (xact->cost && ! xact->cost->commodity)
xact->cost.commodity = commodity_t::null_commodity; xact->cost->commodity = commodity_t::null_commodity;
return xact.release(); return xact.release();
} }
@ -156,8 +154,8 @@ bool finalize_entry(entry_t * entry)
if (! ((*x)->flags & TRANSACTION_VIRTUAL) || if (! ((*x)->flags & TRANSACTION_VIRTUAL) ||
((*x)->flags & TRANSACTION_BALANCE)) { ((*x)->flags & TRANSACTION_BALANCE)) {
DEBUG_PRINT("ledger.textual.finalize", DEBUG_PRINT("ledger.textual.finalize",
"item cost is " << (*x)->cost); "item cost is " << ((*x)->cost ? *(*x)->cost : (*x)->amount));
balance += (*x)->cost; balance += (*x)->cost ? *(*x)->cost : (*x)->amount;
} }
// If one transaction of a two-line transaction is of a different // If one transaction of a two-line transaction is of a different
@ -169,7 +167,7 @@ bool finalize_entry(entry_t * entry)
for (transactions_list::const_iterator x = entry->transactions.begin(); for (transactions_list::const_iterator x = entry->transactions.begin();
x != entry->transactions.end(); x != entry->transactions.end();
x++) { x++) {
if ((*x)->cost != (*x)->amount || ((*x)->flags & TRANSACTION_VIRTUAL)) if ((*x)->cost || ((*x)->flags & TRANSACTION_VIRTUAL))
continue; continue;
for (amounts_map::const_iterator i = balance.amounts.begin(); for (amounts_map::const_iterator i = balance.amounts.begin();
@ -177,9 +175,10 @@ bool finalize_entry(entry_t * entry)
i++) i++)
if ((*i).second.commodity != (*x)->amount.commodity) { if ((*i).second.commodity != (*x)->amount.commodity) {
assert((*x)->amount); assert((*x)->amount);
balance -= (*x)->cost; balance -= (*x)->amount;
(*x)->cost = - (*i).second; assert(! (*x)->cost);
balance += (*x)->cost; (*x)->cost = new amount_t(- (*i).second);
balance += *(*x)->cost;
break; break;
} }
@ -208,7 +207,7 @@ bool finalize_entry(entry_t * entry)
// inverse of the computed value of the others. // inverse of the computed value of the others.
amounts_map::const_iterator i = balance.amounts.begin(); amounts_map::const_iterator i = balance.amounts.begin();
(*x)->amount = (*x)->cost = - balance.amount((*i).first); (*x)->amount = - balance.amount((*i).first);
balance = 0; balance = 0;
} }
@ -401,7 +400,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
time_commodity = amt.commodity; time_commodity = amt.commodity;
transaction_t * xact transaction_t * xact
= new transaction_t(last_account, amt, amt, TRANSACTION_VIRTUAL); = new transaction_t(last_account, amt, TRANSACTION_VIRTUAL);
curr->add_transaction(xact); curr->add_transaction(xact);
if (! finalize_entry(curr.get()) || if (! finalize_entry(curr.get()) ||

View file

@ -83,10 +83,18 @@ void value_expr_t::compute(value_t& result, const details_t& details,
break; break;
case COST: case COST:
if (details.xact) if (details.xact) {
result = details.xact->cost; if (details.xact->cost)
else if (details.account) result = *details.xact->cost;
result = details.account->value.cost; else
result = details.xact->amount;
}
else if (details.account) {
if (details.account->value.cost)
result = *details.account->value.cost;
else
result = details.account->value.quantity;
}
break; break;
case TOTAL: case TOTAL:
@ -96,10 +104,18 @@ void value_expr_t::compute(value_t& result, const details_t& details,
result = details.account->total.quantity; result = details.account->total.quantity;
break; break;
case COST_TOTAL: case COST_TOTAL:
if (details.xact) if (details.xact) {
result = details.xact->total.cost; if (details.xact->total.cost)
else if (details.account) result = *details.xact->total.cost;
result = details.account->total.cost; else
result = details.xact->total.quantity;
}
else if (details.account) {
if (details.account->total.cost)
result = *details.account->total.cost;
else
result = details.account->total.quantity;
}
break; break;
case VALUE_EXPR: case VALUE_EXPR:
@ -163,6 +179,13 @@ void value_expr_t::compute(value_t& result, const details_t& details,
break; break;
case INDEX: case INDEX:
if (details.xact)
result = details.xact->index + 1;
else if (details.account)
result = details.account->subcount;
break;
case COUNT:
if (details.xact) if (details.xact)
result = details.xact->index + 1; result = details.xact->index + 1;
else if (details.account) else if (details.account)
@ -377,7 +400,7 @@ value_expr_t * parse_value_term(std::istream& in)
in.get(c); in.get(c);
switch (c) { switch (c) {
// Basic terms // Basic terms
case 'N': case 'm':
node.reset(new value_expr_t(value_expr_t::CONSTANT_T)); node.reset(new value_expr_t(value_expr_t::CONSTANT_T));
node->constant_t = now; node->constant_t = now;
break; break;
@ -388,6 +411,7 @@ value_expr_t * parse_value_term(std::istream& in)
case 'X': node.reset(new value_expr_t(value_expr_t::CLEARED)); break; case 'X': node.reset(new value_expr_t(value_expr_t::CLEARED)); break;
case 'R': node.reset(new value_expr_t(value_expr_t::REAL)); break; case 'R': node.reset(new value_expr_t(value_expr_t::REAL)); break;
case 'n': node.reset(new value_expr_t(value_expr_t::INDEX)); break; case 'n': node.reset(new value_expr_t(value_expr_t::INDEX)); break;
case 'N': node.reset(new value_expr_t(value_expr_t::COUNT)); break;
case 'l': node.reset(new value_expr_t(value_expr_t::DEPTH)); break; case 'l': node.reset(new value_expr_t(value_expr_t::DEPTH)); break;
case 'O': node.reset(new value_expr_t(value_expr_t::TOTAL)); break; case 'O': node.reset(new value_expr_t(value_expr_t::TOTAL)); break;
case 'C': node.reset(new value_expr_t(value_expr_t::COST_TOTAL)); break; case 'C': node.reset(new value_expr_t(value_expr_t::COST_TOTAL)); break;
@ -715,6 +739,7 @@ void dump_value_expr(std::ostream& out, const value_expr_t * node)
case value_expr_t::CLEARED: out << "CLEARED"; break; case value_expr_t::CLEARED: out << "CLEARED"; break;
case value_expr_t::REAL: out << "REAL"; break; case value_expr_t::REAL: out << "REAL"; break;
case value_expr_t::INDEX: out << "INDEX"; break; case value_expr_t::INDEX: out << "INDEX"; break;
case value_expr_t::COUNT: out << "COUNT"; break;
case value_expr_t::DEPTH: out << "DEPTH"; break; case value_expr_t::DEPTH: out << "DEPTH"; break;
case value_expr_t::TOTAL: out << "TOTAL"; break; case value_expr_t::TOTAL: out << "TOTAL"; break;
case value_expr_t::COST_TOTAL: out << "COST_TOTAL"; break; case value_expr_t::COST_TOTAL: out << "COST_TOTAL"; break;

View file

@ -57,6 +57,7 @@ struct value_expr_t
DEPTH, DEPTH,
// Item totals // Item totals
COUNT,
TOTAL, TOTAL,
COST_TOTAL, COST_TOTAL,

View file

@ -29,7 +29,8 @@ void calc_transactions::operator()(transaction_t * xact)
if (inverted) { if (inverted) {
xact->amount.negate(); xact->amount.negate();
xact->cost.negate(); if (xact->cost)
xact->cost->negate();
} }
if (! (xact->dflags & TRANSACTION_NO_TOTAL)) if (! (xact->dflags & TRANSACTION_NO_TOTAL))
@ -39,7 +40,8 @@ void calc_transactions::operator()(transaction_t * xact)
if (inverted) { if (inverted) {
xact->amount.negate(); xact->amount.negate();
xact->cost.negate(); if (xact->cost)
xact->cost->negate();
} }
last_xact = xact; last_xact = xact;
@ -64,7 +66,6 @@ void collapse_transactions::report_cumulative_subtotal()
total_xact->entry = last_entry; total_xact->entry = last_entry;
total_xact->amount = (*i).second; total_xact->amount = (*i).second;
total_xact->cost = (*i).second;
(*handler)(total_xact); (*handler)(total_xact);
} }
@ -161,7 +162,6 @@ void subtotal_transactions::flush(const char * spec_fmt)
xact->entry = entry; xact->entry = entry;
xact->amount = (*j).second; xact->amount = (*j).second;
xact->cost = (*j).second;
(*handler)(xact); (*handler)(xact);
} }

5
walk.h
View file

@ -121,7 +121,7 @@ class set_account_value : public item_handler<transaction_t>
virtual void operator()(transaction_t * xact) { virtual void operator()(transaction_t * xact) {
xact->account->value += *xact; xact->account->value += *xact;
xact->account->count++; xact->account->subcount++;
if (handler) if (handler)
(*handler)(xact); (*handler)(xact);
@ -364,9 +364,10 @@ inline void sum_accounts(account_t * account) {
i++) { i++) {
sum_accounts((*i).second); sum_accounts((*i).second);
account->total += (*i).second->total; account->total += (*i).second->total;
account->count += (*i).second->count; account->count += (*i).second->count + (*i).second->subcount;
} }
account->total += account->value; account->total += account->value;
account->count += account->subcount;
} }
typedef std::deque<account_t *> accounts_deque; typedef std::deque<account_t *> accounts_deque;