only compute the cost when it differs from the amount
This commit is contained in:
parent
225acd14e5
commit
000bfe1cec
18 changed files with 227 additions and 112 deletions
|
|
@ -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));
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
balance.cc
22
balance.cc
|
|
@ -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
133
balance.h
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
14
binary.cc
14
binary.cc
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
17
ledger.cc
17
ledger.cc
|
|
@ -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)
|
||||||
|
|
|
||||||
19
ledger.h
19
ledger.h
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
10
ledger.texi
10
ledger.texi
|
|
@ -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
3
qif.cc
|
|
@ -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()))
|
||||||
|
|
|
||||||
|
|
@ -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])
|
|
||||||
29
textual.cc
29
textual.cc
|
|
@ -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()) ||
|
||||||
|
|
|
||||||
43
valexpr.cc
43
valexpr.cc
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ struct value_expr_t
|
||||||
DEPTH,
|
DEPTH,
|
||||||
|
|
||||||
// Item totals
|
// Item totals
|
||||||
|
COUNT,
|
||||||
TOTAL,
|
TOTAL,
|
||||||
COST_TOTAL,
|
COST_TOTAL,
|
||||||
|
|
||||||
|
|
|
||||||
8
walk.cc
8
walk.cc
|
|
@ -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
5
walk.h
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue