Factored common parts of entry_t and xact_t into new item_t
This commit is contained in:
parent
43ba0bb038
commit
fdc7a4e4c5
24 changed files with 444 additions and 418 deletions
|
|
@ -38,8 +38,9 @@ endif
|
||||||
|
|
||||||
libledger_la_CPPFLAGS = $(libamounts_la_CPPFLAGS)
|
libledger_la_CPPFLAGS = $(libamounts_la_CPPFLAGS)
|
||||||
libledger_la_LDFLAGS = -release 3.0.0
|
libledger_la_LDFLAGS = -release 3.0.0
|
||||||
libledger_la_SOURCES = \
|
libledger_la_SOURCES = \
|
||||||
src/journal.cc \
|
src/journal.cc \
|
||||||
|
src/item.cc \
|
||||||
src/entry.cc \
|
src/entry.cc \
|
||||||
src/xact.cc \
|
src/xact.cc \
|
||||||
src/account.cc \
|
src/account.cc \
|
||||||
|
|
@ -102,6 +103,7 @@ pkginclude_HEADERS = \
|
||||||
src/option.h \
|
src/option.h \
|
||||||
\
|
\
|
||||||
src/journal.h \
|
src/journal.h \
|
||||||
|
src/item.h \
|
||||||
src/entry.h \
|
src/entry.h \
|
||||||
src/xact.h \
|
src/xact.h \
|
||||||
src/account.h \
|
src/account.h \
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ account_t * account_t::find_account(const string& name,
|
||||||
if (! auto_create)
|
if (! auto_create)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
account = new account_t(owner, this, first);
|
account = new account_t(this, first);
|
||||||
std::pair<accounts_map::iterator, bool> result
|
std::pair<accounts_map::iterator, bool> result
|
||||||
= accounts.insert(accounts_map::value_type(first, account));
|
= accounts.insert(accounts_map::value_type(first, account));
|
||||||
assert(result.second);
|
assert(result.second);
|
||||||
|
|
@ -190,8 +190,7 @@ expr_t::ptr_op_t account_t::lookup(const string& name)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(owner == session_t::current);
|
return session_t::current->current_report->lookup(name);
|
||||||
return owner->current_report->lookup(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool account_t::valid() const
|
bool account_t::valid() const
|
||||||
|
|
@ -234,7 +233,7 @@ void account_t::calculate_sums()
|
||||||
}
|
}
|
||||||
|
|
||||||
call_scope_t args(*this);
|
call_scope_t args(*this);
|
||||||
value_t amount(owner->current_report->get_amount_expr(args));
|
value_t amount(session_t::current->current_report->get_amount_expr(args));
|
||||||
if (! amount.is_null()) {
|
if (! amount.is_null()) {
|
||||||
add_or_set_value(xd.total, amount);
|
add_or_set_value(xd.total, amount);
|
||||||
xd.total_count += xd.count;
|
xd.total_count += xd.count;
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@ class account_t : public scope_t
|
||||||
public:
|
public:
|
||||||
typedef unsigned long ident_t;
|
typedef unsigned long ident_t;
|
||||||
|
|
||||||
session_t * owner;
|
|
||||||
account_t * parent;
|
account_t * parent;
|
||||||
string name;
|
string name;
|
||||||
optional<string> note;
|
optional<string> note;
|
||||||
|
|
@ -58,17 +57,15 @@ class account_t : public scope_t
|
||||||
mutable ident_t ident;
|
mutable ident_t ident;
|
||||||
mutable string _fullname;
|
mutable string _fullname;
|
||||||
|
|
||||||
account_t(session_t * _owner,
|
account_t(account_t * _parent = NULL,
|
||||||
account_t * _parent = NULL,
|
|
||||||
const string& _name = "",
|
const string& _name = "",
|
||||||
const optional<string>& _note = none)
|
const optional<string>& _note = none)
|
||||||
: scope_t(), owner(_owner), parent(_parent), name(_name), note(_note),
|
: scope_t(), parent(_parent), name(_name), note(_note),
|
||||||
depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {
|
depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {
|
||||||
TRACE_CTOR(account_t, "account_t *, const string&, const string&");
|
TRACE_CTOR(account_t, "account_t *, const string&, const string&");
|
||||||
}
|
}
|
||||||
account_t(const account_t& other)
|
account_t(const account_t& other)
|
||||||
: scope_t(),
|
: scope_t(),
|
||||||
owner(other.owner),
|
|
||||||
parent(other.parent),
|
parent(other.parent),
|
||||||
name(other.name),
|
name(other.name),
|
||||||
note(other.note),
|
note(other.note),
|
||||||
|
|
|
||||||
23
src/csv.cc
23
src/csv.cc
|
|
@ -102,28 +102,15 @@ void format_csv_xacts::operator()(xact_t& xact)
|
||||||
}
|
}
|
||||||
out << ',';
|
out << ',';
|
||||||
|
|
||||||
switch (xact.state) {
|
switch (xact.state()) {
|
||||||
case xact_t::CLEARED:
|
case item_t::CLEARED:
|
||||||
write_escaped_string(out, "*");
|
write_escaped_string(out, "*");
|
||||||
break;
|
break;
|
||||||
case xact_t::PENDING:
|
case item_t::PENDING:
|
||||||
write_escaped_string(out, "!");
|
write_escaped_string(out, "!");
|
||||||
break;
|
break;
|
||||||
default: {
|
default:
|
||||||
xact_t::state_t state;
|
break;
|
||||||
if (xact.entry->get_state(&state))
|
|
||||||
switch (state) {
|
|
||||||
case xact_t::CLEARED:
|
|
||||||
write_escaped_string(out, "*");
|
|
||||||
break;
|
|
||||||
case xact_t::PENDING:
|
|
||||||
write_escaped_string(out, "!");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
write_escaped_string(out, "");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
out << ',';
|
out << ',';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ void format_emacs_xacts::write_entry(entry_t& entry)
|
||||||
|
|
||||||
out << (static_cast<unsigned long>(entry.beg_line) + 1) << " ";
|
out << (static_cast<unsigned long>(entry.beg_line) + 1) << " ";
|
||||||
|
|
||||||
tm when = gregorian::to_tm(entry.date());
|
tm when = gregorian::to_tm(*entry.date());
|
||||||
std::time_t date = std::mktime(&when); // jww (2008-04-20): Is this GMT or local?
|
std::time_t date = std::mktime(&when); // jww (2008-04-20): Is this GMT or local?
|
||||||
|
|
||||||
out << "(" << (date / 65536) << " " << (date % 65536) << " 0) ";
|
out << "(" << (date / 65536) << " " << (date % 65536) << " 0) ";
|
||||||
|
|
@ -83,11 +83,11 @@ void format_emacs_xacts::operator()(xact_t& xact)
|
||||||
out << "\"" << xact.reported_account()->fullname() << "\" \""
|
out << "\"" << xact.reported_account()->fullname() << "\" \""
|
||||||
<< xact.amount << "\"";
|
<< xact.amount << "\"";
|
||||||
|
|
||||||
switch (xact.state) {
|
switch (xact.state()) {
|
||||||
case xact_t::CLEARED:
|
case item_t::CLEARED:
|
||||||
out << " t";
|
out << " t";
|
||||||
break;
|
break;
|
||||||
case xact_t::PENDING:
|
case item_t::PENDING:
|
||||||
out << " pending";
|
out << " pending";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
120
src/entry.cc
120
src/entry.cc
|
|
@ -38,8 +38,7 @@
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
entry_base_t::entry_base_t(const entry_base_t& e)
|
entry_base_t::entry_base_t(const entry_base_t& e)
|
||||||
: supports_flags<>(), journal(NULL),
|
: item_t(), journal(NULL)
|
||||||
beg_pos(0), beg_line(0), end_pos(0), end_line(0)
|
|
||||||
{
|
{
|
||||||
TRACE_CTOR(entry_base_t, "copy");
|
TRACE_CTOR(entry_base_t, "copy");
|
||||||
xacts.insert(xacts.end(), e.xacts.begin(), e.xacts.end());
|
xacts.insert(xacts.end(), e.xacts.begin(), e.xacts.end());
|
||||||
|
|
@ -53,8 +52,8 @@ entry_base_t::~entry_base_t()
|
||||||
// If the transaction is a temporary, it will be destructed when the
|
// If the transaction is a temporary, it will be destructed when the
|
||||||
// temporary is. If it's from a binary cache, we can safely destruct it
|
// temporary is. If it's from a binary cache, we can safely destruct it
|
||||||
// but its memory will be deallocated with the cache.
|
// but its memory will be deallocated with the cache.
|
||||||
if (! xact->has_flags(XACT_TEMP)) {
|
if (! xact->has_flags(ITEM_TEMP)) {
|
||||||
if (! xact->has_flags(XACT_IN_CACHE))
|
if (! xact->has_flags(ITEM_IN_CACHE))
|
||||||
checked_delete(xact);
|
checked_delete(xact);
|
||||||
else
|
else
|
||||||
xact->~xact_t();
|
xact->~xact_t();
|
||||||
|
|
@ -62,6 +61,20 @@ entry_base_t::~entry_base_t()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item_t::state_t entry_base_t::state() const
|
||||||
|
{
|
||||||
|
bool first = true;
|
||||||
|
state_t result = UNCLEARED;
|
||||||
|
|
||||||
|
foreach (xact_t * xact, xacts) {
|
||||||
|
if ((result == UNCLEARED && xact->_state != UNCLEARED) ||
|
||||||
|
(result == PENDING && xact->_state == CLEARED))
|
||||||
|
result = xact->_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void entry_base_t::add_xact(xact_t * xact)
|
void entry_base_t::add_xact(xact_t * xact)
|
||||||
{
|
{
|
||||||
xacts.push_back(xact);
|
xacts.push_back(xact);
|
||||||
|
|
@ -133,8 +146,8 @@ bool entry_base_t::finalize()
|
||||||
if (journal && journal->basket && xacts.size() == 1 && ! balance.is_null()) {
|
if (journal && journal->basket && xacts.size() == 1 && ! balance.is_null()) {
|
||||||
// jww (2008-07-24): Need to make the rest of the code aware of what to do
|
// jww (2008-07-24): Need to make the rest of the code aware of what to do
|
||||||
// when it sees a generated xact.
|
// when it sees a generated xact.
|
||||||
null_xact = new xact_t(journal->basket, XACT_GENERATED);
|
null_xact = new xact_t(journal->basket, ITEM_GENERATED);
|
||||||
null_xact->state = (*xacts.begin())->state;
|
null_xact->_state = (*xacts.begin())->_state;
|
||||||
add_xact(null_xact);
|
add_xact(null_xact);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -170,7 +183,7 @@ bool entry_base_t::finalize()
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
add_xact(new xact_t(null_xact->account, pair.second.negate(),
|
add_xact(new xact_t(null_xact->account, pair.second.negate(),
|
||||||
XACT_GENERATED));
|
ITEM_GENERATED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -279,7 +292,7 @@ bool entry_base_t::finalize()
|
||||||
amount_t basis_cost;
|
amount_t basis_cost;
|
||||||
amount_t ann_amount =
|
amount_t ann_amount =
|
||||||
commodity_t::exchange(x_amt, final_cost, basis_cost, xact->cost, none,
|
commodity_t::exchange(x_amt, final_cost, basis_cost, xact->cost, none,
|
||||||
datetime_t(xact->actual_date(),
|
datetime_t(*xact->actual_date(),
|
||||||
time_duration_t(0, 0, 0)),
|
time_duration_t(0, 0, 0)),
|
||||||
entry ? entry->code : optional<string>());
|
entry ? entry->code : optional<string>());
|
||||||
|
|
||||||
|
|
@ -341,8 +354,7 @@ bool entry_base_t::finalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
entry_t::entry_t(const entry_t& e)
|
entry_t::entry_t(const entry_t& e)
|
||||||
: entry_base_t(e), scope_t(), _date(e._date), _date_eff(e._date_eff),
|
: entry_base_t(e), code(e.code), payee(e.payee)
|
||||||
code(e.code), payee(e.payee)
|
|
||||||
{
|
{
|
||||||
TRACE_CTOR(entry_t, "copy");
|
TRACE_CTOR(entry_t, "copy");
|
||||||
|
|
||||||
|
|
@ -350,27 +362,6 @@ entry_t::entry_t(const entry_t& e)
|
||||||
xact->entry = this;
|
xact->entry = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool entry_t::get_state(xact_t::state_t * state) const
|
|
||||||
{
|
|
||||||
bool first = true;
|
|
||||||
bool hetero = false;
|
|
||||||
|
|
||||||
foreach (xact_t * xact, xacts) {
|
|
||||||
if (first ||
|
|
||||||
xact->state == xact_t::CLEARED ||
|
|
||||||
(xact->state == xact_t::PENDING && *state == xact_t::UNCLEARED)) {
|
|
||||||
*state = xact->state;
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
else if (*state != xact->state) {
|
|
||||||
hetero = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ! hetero;
|
|
||||||
}
|
|
||||||
|
|
||||||
void entry_t::add_xact(xact_t * xact)
|
void entry_t::add_xact(xact_t * xact)
|
||||||
{
|
{
|
||||||
xact->entry = this;
|
xact->entry = this;
|
||||||
|
|
@ -378,26 +369,6 @@ void entry_t::add_xact(xact_t * xact)
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
value_t get_date(entry_t& entry) {
|
|
||||||
return entry.date();
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t get_status(entry_t& entry) {
|
|
||||||
xact_t::state_t status;
|
|
||||||
entry.get_state(&status);
|
|
||||||
return long(status);
|
|
||||||
}
|
|
||||||
value_t get_cleared(entry_t& entry) {
|
|
||||||
xact_t::state_t status;
|
|
||||||
entry.get_state(&status);
|
|
||||||
return status == xact_t::CLEARED;
|
|
||||||
}
|
|
||||||
value_t get_pending(entry_t& entry) {
|
|
||||||
xact_t::state_t status;
|
|
||||||
entry.get_state(&status);
|
|
||||||
return status == xact_t::PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t get_code(entry_t& entry) {
|
value_t get_code(entry_t& entry) {
|
||||||
if (entry.code)
|
if (entry.code)
|
||||||
return string_value(*entry.code);
|
return string_value(*entry.code);
|
||||||
|
|
@ -421,49 +392,20 @@ expr_t::ptr_op_t entry_t::lookup(const string& name)
|
||||||
case 'c':
|
case 'c':
|
||||||
if (name == "code")
|
if (name == "code")
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_code>);
|
return WRAP_FUNCTOR(get_wrapper<&get_code>);
|
||||||
else if (name == "cleared")
|
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_cleared>);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'd':
|
|
||||||
if (name[1] == '\0' || name == "date")
|
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_date>);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
if (name[1] == '\0' || name == "payee")
|
if (name[1] == '\0' || name == "payee")
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_payee>);
|
return WRAP_FUNCTOR(get_wrapper<&get_payee>);
|
||||||
else if (name == "pending")
|
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_pending>);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'u':
|
|
||||||
if (name == "uncleared")
|
|
||||||
return expr_t::op_t::wrap_value(1L);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'X':
|
|
||||||
if (name[1] == '\0')
|
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_cleared>);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'Y':
|
|
||||||
if (name[1] == '\0')
|
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_pending>);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (journal) {
|
return item_t::lookup(name);
|
||||||
assert(journal->owner == session_t::current);
|
|
||||||
return journal->owner->current_report->lookup(name);
|
|
||||||
} else {
|
|
||||||
return session_t::current->current_report->lookup(name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool entry_t::valid() const
|
bool entry_t::valid() const
|
||||||
{
|
{
|
||||||
if (! is_valid(_date) || ! journal) {
|
if (! _date || ! journal) {
|
||||||
DEBUG("ledger.validate", "entry_t: ! _date || ! journal");
|
DEBUG("ledger.validate", "entry_t: ! _date || ! journal");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -514,19 +456,11 @@ void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
|
||||||
if (fullname == "$account" || fullname == "@account")
|
if (fullname == "$account" || fullname == "@account")
|
||||||
account = initial_xact->account;
|
account = initial_xact->account;
|
||||||
|
|
||||||
xact_t * new_xact
|
|
||||||
= new xact_t(account, amt, xact->flags() | XACT_AUTO);
|
|
||||||
|
|
||||||
// Copy over details so that the resulting xact is a mirror of
|
// Copy over details so that the resulting xact is a mirror of
|
||||||
// the automated entry's one.
|
// the automated entry's one.
|
||||||
new_xact->state = xact->state;
|
xact_t * new_xact = new xact_t(account, amt);
|
||||||
new_xact->_date = xact->_date;
|
new_xact->copy_details(*xact);
|
||||||
new_xact->_date_eff = xact->_date_eff;
|
new_xact->add_flags(XACT_AUTO);
|
||||||
new_xact->note = xact->note;
|
|
||||||
new_xact->beg_pos = xact->beg_pos;
|
|
||||||
new_xact->beg_line = xact->beg_line;
|
|
||||||
new_xact->end_pos = xact->end_pos;
|
|
||||||
new_xact->end_line = xact->end_line;
|
|
||||||
|
|
||||||
entry.add_xact(new_xact);
|
entry.add_xact(new_xact);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
46
src/entry.h
46
src/entry.h
|
|
@ -39,35 +39,20 @@ namespace ledger {
|
||||||
|
|
||||||
class journal_t;
|
class journal_t;
|
||||||
|
|
||||||
class entry_base_t : public supports_flags<>
|
class entry_base_t : public item_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#define ENTRY_IN_CACHE 0x1
|
journal_t * journal;
|
||||||
|
xacts_list xacts;
|
||||||
|
|
||||||
journal_t * journal;
|
entry_base_t() : journal(NULL) {
|
||||||
string note;
|
|
||||||
unsigned long src_idx;
|
|
||||||
istream_pos_type beg_pos;
|
|
||||||
unsigned long beg_line;
|
|
||||||
istream_pos_type end_pos;
|
|
||||||
unsigned long end_line;
|
|
||||||
xacts_list xacts;
|
|
||||||
|
|
||||||
entry_base_t() : journal(NULL),
|
|
||||||
beg_pos(0), beg_line(0), end_pos(0), end_line(0)
|
|
||||||
{
|
|
||||||
TRACE_CTOR(entry_base_t, "");
|
TRACE_CTOR(entry_base_t, "");
|
||||||
}
|
}
|
||||||
entry_base_t(const entry_base_t& e);
|
entry_base_t(const entry_base_t& e);
|
||||||
|
|
||||||
virtual ~entry_base_t();
|
virtual ~entry_base_t();
|
||||||
|
|
||||||
bool operator==(const entry_base_t& entry) {
|
virtual state_t state() const;
|
||||||
return this == &entry;
|
|
||||||
}
|
|
||||||
bool operator!=(const entry_base_t& entry) {
|
|
||||||
return ! (*this == entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void add_xact(xact_t * xact);
|
virtual void add_xact(xact_t * xact);
|
||||||
virtual bool remove_xact(xact_t * xact);
|
virtual bool remove_xact(xact_t * xact);
|
||||||
|
|
@ -76,11 +61,9 @@ public:
|
||||||
virtual bool valid() const = 0;
|
virtual bool valid() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class entry_t : public entry_base_t, public scope_t
|
class entry_t : public entry_base_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
date_t _date;
|
|
||||||
optional<date_t> _date_eff;
|
|
||||||
optional<string> code;
|
optional<string> code;
|
||||||
string payee;
|
string payee;
|
||||||
|
|
||||||
|
|
@ -93,23 +76,6 @@ public:
|
||||||
TRACE_DTOR(entry_t);
|
TRACE_DTOR(entry_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
date_t actual_date() const {
|
|
||||||
return _date;
|
|
||||||
}
|
|
||||||
date_t effective_date() const {
|
|
||||||
if (! _date_eff)
|
|
||||||
return _date;
|
|
||||||
return *_date_eff;
|
|
||||||
}
|
|
||||||
date_t date() const {
|
|
||||||
if (xact_t::use_effective_date)
|
|
||||||
return effective_date();
|
|
||||||
else
|
|
||||||
return actual_date();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool get_state(xact_t::state_t * state) const;
|
|
||||||
|
|
||||||
virtual void add_xact(xact_t * xact);
|
virtual void add_xact(xact_t * xact);
|
||||||
|
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ void handle_value(const value_t& value,
|
||||||
temps.push_back(xact_t(account));
|
temps.push_back(xact_t(account));
|
||||||
xact_t& xact(temps.back());
|
xact_t& xact(temps.back());
|
||||||
xact.entry = entry;
|
xact.entry = entry;
|
||||||
xact.add_flags(XACT_TEMP);
|
xact.add_flags(ITEM_TEMP);
|
||||||
entry->add_xact(&xact);
|
entry->add_xact(&xact);
|
||||||
|
|
||||||
// If there are component xacts to associate with this
|
// If there are component xacts to associate with this
|
||||||
|
|
@ -390,9 +390,9 @@ void subtotal_xacts::report_subtotal(const char * spec_fmt)
|
||||||
void subtotal_xacts::operator()(xact_t& xact)
|
void subtotal_xacts::operator()(xact_t& xact)
|
||||||
{
|
{
|
||||||
if (! is_valid(start) || xact.date() < start)
|
if (! is_valid(start) || xact.date() < start)
|
||||||
start = xact.date();
|
start = *xact.date();
|
||||||
if (! is_valid(finish) || xact.date() > finish)
|
if (! is_valid(finish) || xact.date() > finish)
|
||||||
finish = xact.date();
|
finish = *xact.date();
|
||||||
|
|
||||||
account_t * acct = xact.reported_account();
|
account_t * acct = xact.reported_account();
|
||||||
assert(acct);
|
assert(acct);
|
||||||
|
|
@ -432,7 +432,7 @@ void interval_xacts::report_subtotal(const date_t& date)
|
||||||
if (is_valid(date))
|
if (is_valid(date))
|
||||||
finish = date - gregorian::days(1);
|
finish = date - gregorian::days(1);
|
||||||
else
|
else
|
||||||
finish = last_xact->date();
|
finish = *last_xact->date();
|
||||||
|
|
||||||
subtotal_xacts::report_subtotal();
|
subtotal_xacts::report_subtotal();
|
||||||
|
|
||||||
|
|
@ -441,7 +441,7 @@ void interval_xacts::report_subtotal(const date_t& date)
|
||||||
|
|
||||||
void interval_xacts::operator()(xact_t& xact)
|
void interval_xacts::operator()(xact_t& xact)
|
||||||
{
|
{
|
||||||
const date_t& date(xact.date());
|
const date_t& date(*xact.date());
|
||||||
|
|
||||||
if ((is_valid(interval.begin) && date < interval.begin) ||
|
if ((is_valid(interval.begin) && date < interval.begin) ||
|
||||||
(is_valid(interval.end) && date >= interval.end))
|
(is_valid(interval.end) && date >= interval.end))
|
||||||
|
|
@ -512,7 +512,7 @@ void by_payee_xacts::operator()(xact_t& xact)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xact.date() > (*i).second->start)
|
if (xact.date() > (*i).second->start)
|
||||||
(*i).second->start = xact.date();
|
(*i).second->start = *xact.date();
|
||||||
|
|
||||||
(*(*i).second)(xact);
|
(*(*i).second)(xact);
|
||||||
}
|
}
|
||||||
|
|
@ -532,8 +532,8 @@ void set_comm_as_payee::operator()(xact_t& xact)
|
||||||
xact_temps.push_back(xact);
|
xact_temps.push_back(xact);
|
||||||
xact_t& temp = xact_temps.back();
|
xact_t& temp = xact_temps.back();
|
||||||
temp.entry = &entry;
|
temp.entry = &entry;
|
||||||
temp.state = xact.state;
|
temp.set_state(xact.state());
|
||||||
temp.add_flags(XACT_TEMP);
|
temp.add_flags(ITEM_TEMP);
|
||||||
|
|
||||||
entry.add_xact(&temp);
|
entry.add_xact(&temp);
|
||||||
|
|
||||||
|
|
@ -554,8 +554,8 @@ void set_code_as_payee::operator()(xact_t& xact)
|
||||||
xact_temps.push_back(xact);
|
xact_temps.push_back(xact);
|
||||||
xact_t& temp = xact_temps.back();
|
xact_t& temp = xact_temps.back();
|
||||||
temp.entry = &entry;
|
temp.entry = &entry;
|
||||||
temp.state = xact.state;
|
temp.set_state(xact.state());
|
||||||
temp.add_flags(XACT_TEMP);
|
temp.add_flags(ITEM_TEMP);
|
||||||
|
|
||||||
entry.add_xact(&temp);
|
entry.add_xact(&temp);
|
||||||
|
|
||||||
|
|
@ -619,7 +619,7 @@ void budget_xacts::report_budget_items(const date_t& date)
|
||||||
xact_temps.push_back(xact);
|
xact_temps.push_back(xact);
|
||||||
xact_t& temp = xact_temps.back();
|
xact_t& temp = xact_temps.back();
|
||||||
temp.entry = &entry;
|
temp.entry = &entry;
|
||||||
temp.add_flags(XACT_AUTO | XACT_TEMP);
|
temp.add_flags(XACT_AUTO | ITEM_TEMP);
|
||||||
temp.amount.negate();
|
temp.amount.negate();
|
||||||
entry.add_xact(&temp);
|
entry.add_xact(&temp);
|
||||||
|
|
||||||
|
|
@ -653,7 +653,7 @@ void budget_xacts::operator()(xact_t& xact)
|
||||||
|
|
||||||
handle:
|
handle:
|
||||||
if (xact_in_budget && flags & BUDGET_BUDGETED) {
|
if (xact_in_budget && flags & BUDGET_BUDGETED) {
|
||||||
report_budget_items(xact.date());
|
report_budget_items(*xact.date());
|
||||||
item_handler<xact_t>::operator()(xact);
|
item_handler<xact_t>::operator()(xact);
|
||||||
}
|
}
|
||||||
else if (! xact_in_budget && flags & BUDGET_UNBUDGETED) {
|
else if (! xact_in_budget && flags & BUDGET_UNBUDGETED) {
|
||||||
|
|
@ -706,7 +706,7 @@ void forecast_xacts::flush()
|
||||||
xact_temps.push_back(xact);
|
xact_temps.push_back(xact);
|
||||||
xact_t& temp = xact_temps.back();
|
xact_t& temp = xact_temps.back();
|
||||||
temp.entry = &entry;
|
temp.entry = &entry;
|
||||||
temp.add_flags(XACT_AUTO | XACT_TEMP);
|
temp.add_flags(XACT_AUTO | ITEM_TEMP);
|
||||||
entry.add_xact(&temp);
|
entry.add_xact(&temp);
|
||||||
|
|
||||||
date_t next = (*least).first.increment(begin);
|
date_t next = (*least).first.increment(begin);
|
||||||
|
|
@ -720,7 +720,7 @@ void forecast_xacts::flush()
|
||||||
temp.xdata().has_flags(XACT_EXT_MATCHES)) {
|
temp.xdata().has_flags(XACT_EXT_MATCHES)) {
|
||||||
if (! pred(temp))
|
if (! pred(temp))
|
||||||
break;
|
break;
|
||||||
last = temp.date();
|
last = *temp.date();
|
||||||
passed.clear();
|
passed.clear();
|
||||||
} else {
|
} else {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
|
||||||
|
|
@ -290,7 +290,7 @@ public:
|
||||||
collapse_xacts(xact_handler_ptr handler, session_t& session)
|
collapse_xacts(xact_handler_ptr handler, session_t& session)
|
||||||
: item_handler<xact_t>(handler), count(0),
|
: item_handler<xact_t>(handler), count(0),
|
||||||
last_entry(NULL), last_xact(NULL),
|
last_entry(NULL), last_xact(NULL),
|
||||||
totals_account(&session, NULL, "<Total>") {
|
totals_account(NULL, "<Total>") {
|
||||||
TRACE_CTOR(collapse_xacts, "xact_handler_ptr");
|
TRACE_CTOR(collapse_xacts, "xact_handler_ptr");
|
||||||
}
|
}
|
||||||
virtual ~collapse_xacts() {
|
virtual ~collapse_xacts() {
|
||||||
|
|
@ -588,7 +588,7 @@ public:
|
||||||
|
|
||||||
virtual void flush();
|
virtual void flush();
|
||||||
virtual void operator()(xact_t& xact) {
|
virtual void operator()(xact_t& xact) {
|
||||||
days_of_the_week[xact.date().day_of_week()].push_back(&xact);
|
days_of_the_week[xact.date()->day_of_week()].push_back(&xact);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ static enum action_t {
|
||||||
static void startElement(void *, const char *name, const char **)
|
static void startElement(void *, const char *name, const char **)
|
||||||
{
|
{
|
||||||
if (std::strcmp(name, "gnc:account") == 0) {
|
if (std::strcmp(name, "gnc:account") == 0) {
|
||||||
curr_account = new account_t(master_account->owner, master_account);
|
curr_account = new account_t(master_account);
|
||||||
}
|
}
|
||||||
else if (std::strcmp(name, "act:name") == 0)
|
else if (std::strcmp(name, "act:name") == 0)
|
||||||
action = ACCOUNT_NAME;
|
action = ACCOUNT_NAME;
|
||||||
|
|
@ -193,7 +193,7 @@ static void endElement(void *, const char *name)
|
||||||
value = curr_quant;
|
value = curr_quant;
|
||||||
}
|
}
|
||||||
|
|
||||||
xact->state = curr_state;
|
xact->set_state(curr_state);
|
||||||
xact->amount = value;
|
xact->amount = value;
|
||||||
if (value != curr_value)
|
if (value != curr_value)
|
||||||
xact->cost = curr_value;
|
xact->cost = curr_value;
|
||||||
|
|
|
||||||
141
src/item.cc
Normal file
141
src/item.cc
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* 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 "item.h"
|
||||||
|
#include "session.h"
|
||||||
|
#include "report.h"
|
||||||
|
|
||||||
|
namespace ledger {
|
||||||
|
|
||||||
|
bool item_t::use_effective_date = false;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
value_t get_status(item_t& item) {
|
||||||
|
return long(item.state());
|
||||||
|
}
|
||||||
|
value_t get_cleared(item_t& item) {
|
||||||
|
return item.state() == item_t::CLEARED;
|
||||||
|
}
|
||||||
|
value_t get_pending(item_t& item) {
|
||||||
|
return item.state() == item_t::PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t get_date(item_t& item) {
|
||||||
|
if (optional<date_t> date = item.date())
|
||||||
|
return *date;
|
||||||
|
else
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t get_note(item_t& item) {
|
||||||
|
return string_value(item.note ? *item.note : empty_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t get_beg_pos(item_t& item) {
|
||||||
|
return long(item.beg_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t get_beg_line(item_t& item) {
|
||||||
|
return long(item.beg_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t get_end_pos(item_t& item) {
|
||||||
|
return long(item.end_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t get_end_line(item_t& item) {
|
||||||
|
return long(item.end_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <value_t (*Func)(item_t&)>
|
||||||
|
value_t get_wrapper(call_scope_t& scope) {
|
||||||
|
return (*Func)(find_scope<item_t>(scope));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_t::ptr_op_t item_t::lookup(const string& name)
|
||||||
|
{
|
||||||
|
switch (name[0]) {
|
||||||
|
case 'c':
|
||||||
|
if (name == "cleared")
|
||||||
|
return WRAP_FUNCTOR(get_wrapper<&get_cleared>);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
if (name[1] == '\0' || name == "date")
|
||||||
|
return WRAP_FUNCTOR(get_wrapper<&get_date>);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
if (name == "note")
|
||||||
|
return WRAP_FUNCTOR(get_wrapper<&get_note>);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
if (name == "pending")
|
||||||
|
return WRAP_FUNCTOR(get_wrapper<&get_pending>);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
if (name == "status")
|
||||||
|
return WRAP_FUNCTOR(get_wrapper<&get_status>);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
if (name == "uncleared")
|
||||||
|
return expr_t::op_t::wrap_value(1L);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
if (name[1] == '\0')
|
||||||
|
return WRAP_FUNCTOR(get_wrapper<&get_cleared>);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Y':
|
||||||
|
if (name[1] == '\0')
|
||||||
|
return WRAP_FUNCTOR(get_wrapper<&get_pending>);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return session_t::current->current_report->lookup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool item_t::valid() const
|
||||||
|
{
|
||||||
|
if (_state != UNCLEARED && _state != CLEARED && _state != PENDING) {
|
||||||
|
DEBUG("ledger.validate", "item_t: state is bad");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ledger
|
||||||
135
src/item.h
Normal file
135
src/item.h
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ITEM_H
|
||||||
|
#define _ITEM_H
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#include "scope.h"
|
||||||
|
|
||||||
|
namespace ledger {
|
||||||
|
|
||||||
|
class entry_t;
|
||||||
|
class account_t;
|
||||||
|
|
||||||
|
class item_t;
|
||||||
|
typedef std::list<item_t *> items_list;
|
||||||
|
|
||||||
|
class item_t : public supports_flags<>, public scope_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
#define ITEM_NORMAL 0x0000 // no flags at all, a basic transaction
|
||||||
|
#define ITEM_IN_CACHE 0x0001 // transaction allocated by the binary cache
|
||||||
|
#define ITEM_GENERATED 0x0002 // transaction was not found in a journal
|
||||||
|
#define ITEM_TEMP 0x0004 // transaction is a temporary object
|
||||||
|
|
||||||
|
enum state_t { UNCLEARED = 0, CLEARED, PENDING };
|
||||||
|
|
||||||
|
state_t _state;
|
||||||
|
|
||||||
|
optional<date_t> _date;
|
||||||
|
optional<date_t> _date_eff;
|
||||||
|
optional<string> note;
|
||||||
|
|
||||||
|
unsigned short src_idx;
|
||||||
|
istream_pos_type beg_pos;
|
||||||
|
unsigned long beg_line;
|
||||||
|
istream_pos_type end_pos;
|
||||||
|
unsigned long end_line;
|
||||||
|
|
||||||
|
static bool use_effective_date;
|
||||||
|
|
||||||
|
item_t(flags_t _flags = ITEM_NORMAL, const optional<string>& _note = none)
|
||||||
|
: supports_flags<>(_flags), _state(UNCLEARED), note(_note),
|
||||||
|
beg_pos(0), beg_line(0), end_pos(0), end_line(0)
|
||||||
|
{
|
||||||
|
TRACE_CTOR(item_t, "flags_t, const string&");
|
||||||
|
}
|
||||||
|
item_t(const item_t& item) : supports_flags<>(), scope_t()
|
||||||
|
{
|
||||||
|
TRACE_CTOR(item_t, "copy");
|
||||||
|
copy_details(item);
|
||||||
|
}
|
||||||
|
virtual ~item_t() {
|
||||||
|
TRACE_DTOR(item_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_details(const item_t& item)
|
||||||
|
{
|
||||||
|
set_flags(item.flags());
|
||||||
|
set_state(item.state());
|
||||||
|
|
||||||
|
_date = item._date;
|
||||||
|
_date_eff = item._date_eff;
|
||||||
|
|
||||||
|
note = item.note;
|
||||||
|
|
||||||
|
beg_pos = item.beg_pos;
|
||||||
|
beg_line = item.beg_line;
|
||||||
|
end_pos = item.end_pos;
|
||||||
|
end_line = item.end_line;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool operator==(const item_t& entry) {
|
||||||
|
return this == &entry;
|
||||||
|
}
|
||||||
|
virtual bool operator!=(const item_t& entry) {
|
||||||
|
return ! (*this == entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual optional<date_t> actual_date() const {
|
||||||
|
return _date;
|
||||||
|
}
|
||||||
|
virtual optional<date_t> effective_date() const {
|
||||||
|
return _date_eff;
|
||||||
|
}
|
||||||
|
optional<date_t> date() const {
|
||||||
|
if (use_effective_date && _date_eff)
|
||||||
|
return effective_date();
|
||||||
|
else
|
||||||
|
return actual_date();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_state(state_t new_state) {
|
||||||
|
_state = new_state;
|
||||||
|
}
|
||||||
|
virtual state_t state() const {
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||||
|
|
||||||
|
bool valid() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ledger
|
||||||
|
|
||||||
|
#endif // _ITEM_H
|
||||||
|
|
@ -36,11 +36,10 @@ namespace ledger {
|
||||||
|
|
||||||
const string version = PACKAGE_VERSION;
|
const string version = PACKAGE_VERSION;
|
||||||
|
|
||||||
journal_t::journal_t(session_t * _owner)
|
journal_t::journal_t() : basket(NULL)
|
||||||
: owner(_owner), basket(NULL)
|
|
||||||
{
|
{
|
||||||
TRACE_CTOR(journal_t, "");
|
TRACE_CTOR(journal_t, "");
|
||||||
master = owner->master.get();
|
master = session_t::current->master.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
journal_t::~journal_t()
|
journal_t::~journal_t()
|
||||||
|
|
@ -51,19 +50,19 @@ journal_t::~journal_t()
|
||||||
// accounts they refer to, because all accounts are about to
|
// accounts they refer to, because all accounts are about to
|
||||||
// be deleted.
|
// be deleted.
|
||||||
foreach (entry_t * entry, entries)
|
foreach (entry_t * entry, entries)
|
||||||
if (! entry->has_flags(ENTRY_IN_CACHE))
|
if (! entry->has_flags(ITEM_IN_CACHE))
|
||||||
checked_delete(entry);
|
checked_delete(entry);
|
||||||
else
|
else
|
||||||
entry->~entry_t();
|
entry->~entry_t();
|
||||||
|
|
||||||
foreach (auto_entry_t * entry, auto_entries)
|
foreach (auto_entry_t * entry, auto_entries)
|
||||||
if (! entry->has_flags(ENTRY_IN_CACHE))
|
if (! entry->has_flags(ITEM_IN_CACHE))
|
||||||
checked_delete(entry);
|
checked_delete(entry);
|
||||||
else
|
else
|
||||||
entry->~auto_entry_t();
|
entry->~auto_entry_t();
|
||||||
|
|
||||||
foreach (period_entry_t * entry, period_entries)
|
foreach (period_entry_t * entry, period_entries)
|
||||||
if (! entry->has_flags(ENTRY_IN_CACHE))
|
if (! entry->has_flags(ITEM_IN_CACHE))
|
||||||
checked_delete(entry);
|
checked_delete(entry);
|
||||||
else
|
else
|
||||||
entry->~period_entry_t();
|
entry->~period_entry_t();
|
||||||
|
|
@ -71,22 +70,22 @@ journal_t::~journal_t()
|
||||||
|
|
||||||
void journal_t::add_account(account_t * acct)
|
void journal_t::add_account(account_t * acct)
|
||||||
{
|
{
|
||||||
owner->add_account(acct);
|
session_t::current->add_account(acct);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool journal_t::remove_account(account_t * acct)
|
bool journal_t::remove_account(account_t * acct)
|
||||||
{
|
{
|
||||||
return owner->remove_account(acct);
|
return session_t::current->remove_account(acct);
|
||||||
}
|
}
|
||||||
|
|
||||||
account_t * journal_t::find_account(const string& name, bool auto_create)
|
account_t * journal_t::find_account(const string& name, bool auto_create)
|
||||||
{
|
{
|
||||||
return owner->find_account(name, auto_create);
|
return session_t::current->find_account(name, auto_create);
|
||||||
}
|
}
|
||||||
|
|
||||||
account_t * journal_t::find_account_re(const string& regexp)
|
account_t * journal_t::find_account_re(const string& regexp)
|
||||||
{
|
{
|
||||||
return owner->find_account_re(regexp);
|
return session_t::current->find_account_re(regexp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool journal_t::add_entry(entry_t * entry)
|
bool journal_t::add_entry(entry_t * entry)
|
||||||
|
|
@ -105,7 +104,7 @@ bool journal_t::add_entry(entry_t * entry)
|
||||||
foreach (const xact_t * xact, entry->xacts)
|
foreach (const xact_t * xact, entry->xacts)
|
||||||
if (xact->cost) {
|
if (xact->cost) {
|
||||||
assert(xact->amount);
|
assert(xact->amount);
|
||||||
xact->amount.commodity().add_price(datetime_t(entry->date(),
|
xact->amount.commodity().add_price(datetime_t(*entry->date(),
|
||||||
time_duration_t(0, 0, 0)),
|
time_duration_t(0, 0, 0)),
|
||||||
*xact->cost / xact->amount.number());
|
*xact->cost / xact->amount.number());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@ class account_t;
|
||||||
class journal_t : public noncopyable
|
class journal_t : public noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
session_t * owner;
|
|
||||||
account_t * master;
|
account_t * master;
|
||||||
account_t * basket;
|
account_t * basket;
|
||||||
entries_list entries;
|
entries_list entries;
|
||||||
|
|
@ -58,11 +57,11 @@ public:
|
||||||
|
|
||||||
hooks_t<entry_finalizer_t, entry_t> entry_finalize_hooks;
|
hooks_t<entry_finalizer_t, entry_t> entry_finalize_hooks;
|
||||||
|
|
||||||
journal_t(session_t * _owner);
|
journal_t();
|
||||||
~journal_t();
|
~journal_t();
|
||||||
|
|
||||||
// These four methods are delegated to 'owner', since all accounts processed
|
// These four methods are delegated to the current session, since all
|
||||||
// are gathered together at the session level.
|
// accounts processed are gathered together at the session level.
|
||||||
void add_account(account_t * acct);
|
void add_account(account_t * acct);
|
||||||
bool remove_account(account_t * acct);
|
bool remove_account(account_t * acct);
|
||||||
account_t * find_account(const string& name, bool auto_create = true);
|
account_t * find_account(const string& name, bool auto_create = true);
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,7 @@ int ofx_proc_account_cb(struct OfxAccountData data, void *)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
DEBUG("ledger.ofx.parse", "account " << data.account_name);
|
DEBUG("ledger.ofx.parse", "account " << data.account_name);
|
||||||
account_t * account = new account_t(master_account->owner, master_account,
|
account_t * account = new account_t(master_account, data.account_name);
|
||||||
data.account_name);
|
|
||||||
curr_journal->add_account(account);
|
curr_journal->add_account(account);
|
||||||
ofx_accounts.insert(accounts_pair(data.account_id, account));
|
ofx_accounts.insert(accounts_pair(data.account_id, account));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,7 @@ format_equity::format_equity(report_t& _report, const string& _format)
|
||||||
|
|
||||||
void format_equity::flush()
|
void format_equity::flush()
|
||||||
{
|
{
|
||||||
account_t summary(&report.session, NULL, "Equity:Opening Balances");
|
account_t summary(NULL, "Equity:Opening Balances");
|
||||||
|
|
||||||
account_t::xdata_t& xdata(summary.xdata());
|
account_t::xdata_t& xdata(summary.xdata());
|
||||||
std::ostream& out(*report.output_stream);
|
std::ostream& out(*report.output_stream);
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
|
||||||
c = in.peek();
|
c = in.peek();
|
||||||
if (c == '*' || c == 'X') {
|
if (c == '*' || c == 'X') {
|
||||||
in.get(c);
|
in.get(c);
|
||||||
xact->state = xact_t::CLEARED;
|
xact->set_state(item_t::CLEARED);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,12 +72,12 @@ void reconcile_xacts::flush()
|
||||||
|
|
||||||
foreach (xact_t * xact, xacts) {
|
foreach (xact_t * xact, xacts) {
|
||||||
if (! is_valid(cutoff) || xact->date() < cutoff) {
|
if (! is_valid(cutoff) || xact->date() < cutoff) {
|
||||||
switch (xact->state) {
|
switch (xact->state()) {
|
||||||
case xact_t::CLEARED:
|
case item_t::CLEARED:
|
||||||
cleared_balance += xact->amount;
|
cleared_balance += xact->amount;
|
||||||
break;
|
break;
|
||||||
case xact_t::UNCLEARED:
|
case item_t::UNCLEARED:
|
||||||
case xact_t::PENDING:
|
case item_t::PENDING:
|
||||||
pending_balance += xact->amount;
|
pending_balance += xact->amount;
|
||||||
*last_ptr = xact;
|
*last_ptr = xact;
|
||||||
last_ptr = xact_next_ptr(xact);
|
last_ptr = xact_next_ptr(xact);
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ session_t::session_t()
|
||||||
ansi_codes(false),
|
ansi_codes(false),
|
||||||
ansi_invert(false),
|
ansi_invert(false),
|
||||||
|
|
||||||
master(new account_t(this, NULL, ""))
|
master(new account_t(NULL, ""))
|
||||||
{
|
{
|
||||||
TRACE_CTOR(session_t, "");
|
TRACE_CTOR(session_t, "");
|
||||||
}
|
}
|
||||||
|
|
@ -161,7 +161,7 @@ void session_t::read_init()
|
||||||
|
|
||||||
ifstream init(*init_file);
|
ifstream init(*init_file);
|
||||||
|
|
||||||
journal_t temp(this);
|
journal_t temp;
|
||||||
if (read_journal(temp, *init_file) > 0 ||
|
if (read_journal(temp, *init_file) > 0 ||
|
||||||
temp.auto_entries.size() > 0 ||
|
temp.auto_entries.size() > 0 ||
|
||||||
temp.period_entries.size() > 0)
|
temp.period_entries.size() > 0)
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ public:
|
||||||
virtual ~session_t();
|
virtual ~session_t();
|
||||||
|
|
||||||
journal_t * create_journal() {
|
journal_t * create_journal() {
|
||||||
journal_t * journal = new journal_t(this);
|
journal_t * journal = new journal_t;
|
||||||
journals.push_back(journal);
|
journals.push_back(journal);
|
||||||
return journal;
|
return journal;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,14 +127,14 @@ xact_t * parse_xact(char * line, account_t * account, entry_t * entry = NULL)
|
||||||
char p = peek_next_nonws(in);
|
char p = peek_next_nonws(in);
|
||||||
switch (p) {
|
switch (p) {
|
||||||
case '*':
|
case '*':
|
||||||
xact->state = xact_t::CLEARED;
|
xact->set_state(item_t::CLEARED);
|
||||||
in.get(p);
|
in.get(p);
|
||||||
p = peek_next_nonws(in);
|
p = peek_next_nonws(in);
|
||||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||||
"Parsed the CLEARED flag");
|
"Parsed the CLEARED flag");
|
||||||
break;
|
break;
|
||||||
case '!':
|
case '!':
|
||||||
xact->state = xact_t::PENDING;
|
xact->set_state(item_t::PENDING);
|
||||||
in.get(p);
|
in.get(p);
|
||||||
p = peek_next_nonws(in);
|
p = peek_next_nonws(in);
|
||||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||||
|
|
@ -160,15 +160,17 @@ xact_t * parse_xact(char * line, account_t * account, entry_t * entry = NULL)
|
||||||
|
|
||||||
char * b = &line[long(account_beg)];
|
char * b = &line[long(account_beg)];
|
||||||
char * e = &line[long(account_end)];
|
char * e = &line[long(account_end)];
|
||||||
|
|
||||||
if ((*b == '[' && *(e - 1) == ']') ||
|
if ((*b == '[' && *(e - 1) == ']') ||
|
||||||
(*b == '(' && *(e - 1) == ')')) {
|
(*b == '(' && *(e - 1) == ')')) {
|
||||||
xact->add_flags(XACT_VIRTUAL);
|
xact->add_flags(XACT_VIRTUAL);
|
||||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
DEBUG("ledger.textual.parse",
|
||||||
"Parsed a virtual account name");
|
"line " << linenum << ": " << "Parsed a virtual account name");
|
||||||
|
|
||||||
if (*b == '[') {
|
if (*b == '[') {
|
||||||
xact->add_flags(XACT_BALANCE);
|
xact->add_flags(XACT_BALANCE);
|
||||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
DEBUG("ledger.textual.parse",
|
||||||
"Parsed a balanced virtual account name");
|
"line " << linenum << ": " << "Transaction must balance");
|
||||||
}
|
}
|
||||||
b++; e--;
|
b++; e--;
|
||||||
}
|
}
|
||||||
|
|
@ -374,7 +376,7 @@ xact_t * parse_xact(char * line, account_t * account, entry_t * entry = NULL)
|
||||||
diff -= xact->amount;
|
diff -= xact->amount;
|
||||||
if (! diff.is_zero()) {
|
if (! diff.is_zero()) {
|
||||||
xact_t * temp = new xact_t(xact->account, diff,
|
xact_t * temp = new xact_t(xact->account, diff,
|
||||||
XACT_GENERATED | XACT_CALCULATED);
|
ITEM_GENERATED | XACT_CALCULATED);
|
||||||
entry->add_xact(temp);
|
entry->add_xact(temp);
|
||||||
|
|
||||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||||
|
|
@ -496,15 +498,15 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
|
||||||
|
|
||||||
// Parse the optional cleared flag: *
|
// Parse the optional cleared flag: *
|
||||||
|
|
||||||
xact_t::state_t state = xact_t::UNCLEARED;
|
item_t::state_t state = item_t::UNCLEARED;
|
||||||
if (next) {
|
if (next) {
|
||||||
switch (*next) {
|
switch (*next) {
|
||||||
case '*':
|
case '*':
|
||||||
state = xact_t::CLEARED;
|
state = item_t::CLEARED;
|
||||||
next = skip_ws(++next);
|
next = skip_ws(++next);
|
||||||
break;
|
break;
|
||||||
case '!':
|
case '!':
|
||||||
state = xact_t::PENDING;
|
state = item_t::PENDING;
|
||||||
next = skip_ws(++next);
|
next = skip_ws(++next);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -556,14 +558,13 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xact_t * xact = parse_xact(line, master, curr.get())) {
|
if (xact_t * xact = parse_xact(line, master, curr.get())) {
|
||||||
if (state != xact_t::UNCLEARED &&
|
xact->set_state(state);
|
||||||
xact->state == xact_t::UNCLEARED)
|
|
||||||
xact->state = state;
|
|
||||||
|
|
||||||
xact->beg_pos = beg_pos;
|
xact->beg_pos = beg_pos;
|
||||||
xact->beg_line = beg_line;
|
xact->beg_line = beg_line;
|
||||||
xact->end_pos = end_pos;
|
xact->end_pos = end_pos;
|
||||||
xact->end_line = linenum;
|
xact->end_line = linenum;
|
||||||
|
|
||||||
pos = end_pos;
|
pos = end_pos;
|
||||||
|
|
||||||
curr->add_xact(xact);
|
curr->add_xact(xact);
|
||||||
|
|
@ -674,9 +675,8 @@ static void clock_out_from_timelog(std::list<time_entry_t>& time_entries,
|
||||||
amt.parse(buf);
|
amt.parse(buf);
|
||||||
assert(amt.valid());
|
assert(amt.valid());
|
||||||
|
|
||||||
xact_t * xact
|
xact_t * xact = new xact_t(event.account, amt, XACT_VIRTUAL);
|
||||||
= new xact_t(event.account, amt, XACT_VIRTUAL);
|
xact->set_state(item_t::CLEARED);
|
||||||
xact->state = xact_t::CLEARED;
|
|
||||||
curr->add_xact(xact);
|
curr->add_xact(xact);
|
||||||
|
|
||||||
if (! journal.add_entry(curr.get()))
|
if (! journal.add_entry(curr.get()))
|
||||||
|
|
|
||||||
155
src/xact.cc
155
src/xact.cc
|
|
@ -36,48 +36,32 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
bool xact_t::use_effective_date = false;
|
optional<date_t> xact_t::actual_date() const
|
||||||
|
|
||||||
xact_t::~xact_t()
|
|
||||||
{
|
{
|
||||||
TRACE_DTOR(xact_t);
|
optional<date_t> date = item_t::actual_date();
|
||||||
}
|
if (! date && entry)
|
||||||
|
|
||||||
date_t xact_t::actual_date() const
|
|
||||||
{
|
|
||||||
if (! _date && entry)
|
|
||||||
return entry->actual_date();
|
return entry->actual_date();
|
||||||
return *_date;
|
return date;
|
||||||
}
|
}
|
||||||
|
|
||||||
date_t xact_t::effective_date() const
|
optional<date_t> xact_t::effective_date() const
|
||||||
{
|
{
|
||||||
if (! _date_eff && entry)
|
optional<date_t> date = item_t::effective_date();
|
||||||
|
if (! date && entry)
|
||||||
return entry->effective_date();
|
return entry->effective_date();
|
||||||
return *_date_eff;
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_t::state_t xact_t::state() const
|
||||||
|
{
|
||||||
|
state_t entry_state = entry->state();
|
||||||
|
if ((_state == UNCLEARED && entry_state != UNCLEARED) ||
|
||||||
|
(_state == PENDING && entry_state == CLEARED))
|
||||||
|
return entry_state;
|
||||||
|
return _state;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
value_t get_state(xact_t& xact) {
|
|
||||||
return long(xact.state);
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t state_uncleared(call_scope_t&) {
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t state_cleared(call_scope_t&) {
|
|
||||||
return 1L;
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t state_pending(call_scope_t&) {
|
|
||||||
return 2L;
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t get_date(xact_t& xact) {
|
|
||||||
return xact.date();
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t get_code(xact_t& xact) {
|
value_t get_code(xact_t& xact) {
|
||||||
if (xact.entry->code)
|
if (xact.entry->code)
|
||||||
return string_value(*xact.entry->code);
|
return string_value(*xact.entry->code);
|
||||||
|
|
@ -85,22 +69,6 @@ namespace {
|
||||||
return string_value(empty_string);
|
return string_value(empty_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t get_status(xact_t& xact) {
|
|
||||||
xact_t::state_t status;
|
|
||||||
xact.entry->get_state(&status);
|
|
||||||
return long(status);
|
|
||||||
}
|
|
||||||
value_t get_cleared(xact_t& xact) {
|
|
||||||
xact_t::state_t status;
|
|
||||||
xact.entry->get_state(&status);
|
|
||||||
return status == xact_t::CLEARED;
|
|
||||||
}
|
|
||||||
value_t get_pending(xact_t& xact) {
|
|
||||||
xact_t::state_t status;
|
|
||||||
xact.entry->get_state(&status);
|
|
||||||
return status == xact_t::PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t get_payee(xact_t& xact) {
|
value_t get_payee(xact_t& xact) {
|
||||||
return string_value(xact.entry->payee);
|
return string_value(xact.entry->payee);
|
||||||
}
|
}
|
||||||
|
|
@ -125,10 +93,6 @@ namespace {
|
||||||
return xact.cost ? *xact.cost : xact.amount;
|
return xact.cost ? *xact.cost : xact.amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t get_note(xact_t& xact) {
|
|
||||||
return string_value(xact.note ? *xact.note : empty_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t get_account(call_scope_t& scope)
|
value_t get_account(call_scope_t& scope)
|
||||||
{
|
{
|
||||||
xact_t& xact(downcast<xact_t>(*scope.parent));
|
xact_t& xact(downcast<xact_t>(*scope.parent));
|
||||||
|
|
@ -153,22 +117,6 @@ namespace {
|
||||||
return string_value(xact.reported_account()->name);
|
return string_value(xact.reported_account()->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t get_beg_pos(xact_t& xact) {
|
|
||||||
return long(xact.beg_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t get_beg_line(xact_t& xact) {
|
|
||||||
return long(xact.beg_line);
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t get_end_pos(xact_t& xact) {
|
|
||||||
return long(xact.end_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t get_end_line(xact_t& xact) {
|
|
||||||
return long(xact.end_line);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <value_t (*Func)(xact_t&)>
|
template <value_t (*Func)(xact_t&)>
|
||||||
value_t get_wrapper(call_scope_t& scope) {
|
value_t get_wrapper(call_scope_t& scope) {
|
||||||
return (*Func)(find_scope<xact_t>(scope));
|
return (*Func)(find_scope<xact_t>(scope));
|
||||||
|
|
@ -188,68 +136,29 @@ expr_t::ptr_op_t xact_t::lookup(const string& name)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
if (name == "cleared")
|
if (name == "code")
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_cleared>);
|
|
||||||
else if (name == "code")
|
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_code>);
|
return WRAP_FUNCTOR(get_wrapper<&get_code>);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
|
||||||
if (name[1] == '\0' || name == "date")
|
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_date>);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'f':
|
|
||||||
if (name.find("fmt_") == 0) {
|
|
||||||
switch (name[4]) {
|
|
||||||
case 'A':
|
|
||||||
return WRAP_FUNCTOR(get_account);
|
|
||||||
case 'D':
|
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_date>);
|
|
||||||
case 'P':
|
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_payee>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'n':
|
|
||||||
if (name == "note")
|
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_note>);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
if (name == "pending")
|
if (name == "payee")
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_pending>);
|
|
||||||
else if (name == "payee")
|
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_payee>);
|
return WRAP_FUNCTOR(get_wrapper<&get_payee>);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
|
||||||
if (name == "status")
|
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_status>);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
if (name[1] == '\0' || name == "total")
|
if (name[1] == '\0' || name == "total")
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_total>);
|
return WRAP_FUNCTOR(get_wrapper<&get_total>);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'u':
|
|
||||||
if (name == "uncleared")
|
|
||||||
return expr_t::op_t::wrap_value(1L);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'X':
|
|
||||||
if (name[1] == '\0')
|
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_cleared>);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'Y':
|
|
||||||
if (name[1] == '\0')
|
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_pending>);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// jww (2008-09-19): I don't think we can lookup in entry, because
|
||||||
|
// that means the functor returned would be expecting an entry to be
|
||||||
|
// passed to it, rather than a transaction.
|
||||||
return entry->lookup(name);
|
return entry->lookup(name);
|
||||||
|
#else
|
||||||
|
return item_t::lookup(name);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool xact_t::valid() const
|
bool xact_t::valid() const
|
||||||
|
|
@ -259,11 +168,6 @@ bool xact_t::valid() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state != UNCLEARED && state != CLEARED && state != PENDING) {
|
|
||||||
DEBUG("ledger.validate", "xact_t: state is bad");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
xacts_list::const_iterator i =
|
xacts_list::const_iterator i =
|
||||||
std::find(entry->xacts.begin(),
|
std::find(entry->xacts.begin(),
|
||||||
entry->xacts.end(), this);
|
entry->xacts.end(), this);
|
||||||
|
|
@ -287,11 +191,6 @@ bool xact_t::valid() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags() & ~0x003f) {
|
|
||||||
DEBUG("ledger.validate", "xact_t: flags are bad");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
87
src/xact.h
87
src/xact.h
|
|
@ -32,8 +32,7 @@
|
||||||
#ifndef _XACT_H
|
#ifndef _XACT_H
|
||||||
#define _XACT_H
|
#define _XACT_H
|
||||||
|
|
||||||
#include "utils.h"
|
#include "item.h"
|
||||||
#include "scope.h"
|
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
|
@ -43,90 +42,59 @@ class account_t;
|
||||||
class xact_t;
|
class xact_t;
|
||||||
typedef std::list<xact_t *> xacts_list;
|
typedef std::list<xact_t *> xacts_list;
|
||||||
|
|
||||||
class xact_t : public supports_flags<>, public scope_t
|
class xact_t : public item_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#define XACT_NORMAL 0x0000 // no flags at all, a basic transaction
|
#define XACT_VIRTUAL 0x0100 // the account was specified with (parens)
|
||||||
#define XACT_VIRTUAL 0x0001 // the account was specified with (parens)
|
#define XACT_BALANCE 0x0200 // the account was specified with [brackets]
|
||||||
#define XACT_BALANCE 0x0002 // the account was specified with [brackets]
|
#define XACT_AUTO 0x0400 // transaction created by automated entry
|
||||||
#define XACT_AUTO 0x0004 // transaction created by automated entry
|
#define XACT_CALCULATED 0x0800 // transaction's amount was auto-calculated
|
||||||
#define XACT_IN_CACHE 0x0008 // transaction allocated by the binary cache
|
|
||||||
#define XACT_CALCULATED 0x0010 // transaction's amount was auto-calculated
|
|
||||||
#define XACT_GENERATED 0x0020 // transaction was not found in a journal
|
|
||||||
#define XACT_TEMP 0x0040 // transaction is a temporary object
|
|
||||||
|
|
||||||
enum state_t { UNCLEARED = 0, CLEARED, PENDING };
|
entry_t * entry; // only set for xacts of regular entries
|
||||||
|
|
||||||
entry_t * entry;
|
|
||||||
account_t * account;
|
account_t * account;
|
||||||
state_t state;
|
|
||||||
|
|
||||||
optional<date_t> _date;
|
amount_t amount; // can be null until finalization
|
||||||
optional<date_t> _date_eff;
|
|
||||||
optional<string> note;
|
|
||||||
|
|
||||||
amount_t amount;
|
|
||||||
optional<expr_t> amount_expr;
|
optional<expr_t> amount_expr;
|
||||||
optional<amount_t> cost;
|
optional<amount_t> cost;
|
||||||
optional<expr_t> cost_expr;
|
optional<expr_t> cost_expr;
|
||||||
optional<amount_t> assigned_amount;
|
optional<amount_t> assigned_amount;
|
||||||
optional<expr_t> assigned_amount_expr;
|
optional<expr_t> assigned_amount_expr;
|
||||||
|
|
||||||
istream_pos_type beg_pos;
|
|
||||||
unsigned long beg_line;
|
|
||||||
istream_pos_type end_pos;
|
|
||||||
unsigned long end_line;
|
|
||||||
|
|
||||||
static bool use_effective_date;
|
|
||||||
|
|
||||||
xact_t(account_t * _account = NULL,
|
xact_t(account_t * _account = NULL,
|
||||||
flags_t _flags = XACT_NORMAL)
|
flags_t _flags = ITEM_NORMAL)
|
||||||
: supports_flags<>(_flags), entry(NULL), account(_account),
|
: item_t(_flags),
|
||||||
state(UNCLEARED), beg_pos(0), beg_line(0), end_pos(0), end_line(0)
|
entry(NULL), account(_account)
|
||||||
{
|
{
|
||||||
TRACE_CTOR(xact_t, "account_t *, flags_t");
|
TRACE_CTOR(xact_t, "account_t *, flags_t");
|
||||||
}
|
}
|
||||||
xact_t(account_t * _account,
|
xact_t(account_t * _account,
|
||||||
const amount_t& _amount,
|
const amount_t& _amount,
|
||||||
flags_t _flags = XACT_NORMAL,
|
flags_t _flags = ITEM_NORMAL,
|
||||||
const optional<string>& _note = none)
|
const optional<string>& _note = none)
|
||||||
: supports_flags<>(_flags), entry(NULL), account(_account),
|
: item_t(_flags, _note),
|
||||||
state(UNCLEARED), note(_note), amount(_amount),
|
entry(NULL), account(_account), amount(_amount)
|
||||||
beg_pos(0), beg_line(0), end_pos(0), end_line(0)
|
|
||||||
{
|
{
|
||||||
TRACE_CTOR(xact_t,
|
TRACE_CTOR(xact_t, "account_t *, const amount_t&, flags_t, const optional<string>&");
|
||||||
"account_t *, const amount_t&, flags_t, const string&");
|
|
||||||
}
|
}
|
||||||
xact_t(const xact_t& xact)
|
xact_t(const xact_t& xact)
|
||||||
: supports_flags<>(xact),
|
: item_t(xact),
|
||||||
scope_t(),
|
|
||||||
entry(xact.entry),
|
entry(xact.entry),
|
||||||
account(xact.account),
|
account(xact.account),
|
||||||
state(xact.state),
|
|
||||||
_date(xact._date),
|
|
||||||
_date_eff(xact._date_eff),
|
|
||||||
note(xact.note),
|
|
||||||
amount(xact.amount),
|
amount(xact.amount),
|
||||||
cost(xact.cost),
|
cost(xact.cost),
|
||||||
beg_pos(xact.beg_pos),
|
|
||||||
beg_line(xact.beg_line),
|
|
||||||
end_pos(xact.end_pos),
|
|
||||||
end_line(xact.end_line),
|
|
||||||
xdata_(xact.xdata_) // jww (2008-07-19): What are the copy semantics?
|
xdata_(xact.xdata_) // jww (2008-07-19): What are the copy semantics?
|
||||||
{
|
{
|
||||||
TRACE_CTOR(xact_t, "copy");
|
TRACE_CTOR(xact_t, "copy");
|
||||||
}
|
}
|
||||||
~xact_t();
|
~xact_t() {
|
||||||
|
TRACE_DTOR(xact_t);
|
||||||
date_t actual_date() const;
|
|
||||||
date_t effective_date() const;
|
|
||||||
date_t date() const {
|
|
||||||
if (use_effective_date)
|
|
||||||
return effective_date();
|
|
||||||
else
|
|
||||||
return actual_date();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual optional<date_t> actual_date() const;
|
||||||
|
virtual optional<date_t> effective_date() const;
|
||||||
|
|
||||||
|
virtual state_t state() const;
|
||||||
|
|
||||||
bool must_balance() const {
|
bool must_balance() const {
|
||||||
return ! has_flags(XACT_VIRTUAL) || has_flags(XACT_BALANCE);
|
return ! has_flags(XACT_VIRTUAL) || has_flags(XACT_BALANCE);
|
||||||
}
|
}
|
||||||
|
|
@ -221,8 +189,7 @@ public:
|
||||||
date_t reported_date() const {
|
date_t reported_date() const {
|
||||||
if (xdata_ && is_valid(xdata_->date))
|
if (xdata_ && is_valid(xdata_->date))
|
||||||
return xdata_->date;
|
return xdata_->date;
|
||||||
return
|
return *date();
|
||||||
date();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
account_t * reported_account() {
|
account_t * reported_account() {
|
||||||
|
|
@ -235,6 +202,8 @@ public:
|
||||||
const account_t * reported_account() const {
|
const account_t * reported_account() const {
|
||||||
return const_cast<xact_t *>(this)->reported_account();
|
return const_cast<xact_t *>(this)->reported_account();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend class entry_t;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
12
src/xml.cc
12
src/xml.cc
|
|
@ -64,8 +64,8 @@ static void startElement(void *userData, const char *name, const char **attrs)
|
||||||
else if (std::strcmp(name, "xact") == 0) {
|
else if (std::strcmp(name, "xact") == 0) {
|
||||||
assert(curr_entry);
|
assert(curr_entry);
|
||||||
curr_entry->add_xact(new xact_t);
|
curr_entry->add_xact(new xact_t);
|
||||||
if (curr_state != xact_t::UNCLEARED)
|
if (curr_state != item_t::UNCLEARED)
|
||||||
curr_entry->xacts.back()->state = curr_state;
|
curr_entry->xacts.back()->set_state(curr_state);
|
||||||
}
|
}
|
||||||
else if (std::strcmp(name, "commodity") == 0) {
|
else if (std::strcmp(name, "commodity") == 0) {
|
||||||
if (string(attrs[0]) == "flags")
|
if (string(attrs[0]) == "flags")
|
||||||
|
|
@ -122,10 +122,10 @@ static void endElement(void *userData, const char *name)
|
||||||
curr_entry->xacts.back()->account = curr_journal->find_account(data);
|
curr_entry->xacts.back()->account = curr_journal->find_account(data);
|
||||||
}
|
}
|
||||||
else if (std::strcmp(name, "tr:cleared") == 0) {
|
else if (std::strcmp(name, "tr:cleared") == 0) {
|
||||||
curr_entry->xacts.back()->state = xact_t::CLEARED;
|
curr_entry->xacts.back()->set_state(item_t::CLEARED);
|
||||||
}
|
}
|
||||||
else if (std::strcmp(name, "tr:pending") == 0) {
|
else if (std::strcmp(name, "tr:pending") == 0) {
|
||||||
curr_entry->xacts.back()->state = xact_t::PENDING;
|
curr_entry->xacts.back()->set_state(item_t::PENDING);
|
||||||
}
|
}
|
||||||
else if (std::strcmp(name, "tr:virtual") == 0) {
|
else if (std::strcmp(name, "tr:virtual") == 0) {
|
||||||
curr_entry->xacts.back()->add_flags(XACT_VIRTUAL);
|
curr_entry->xacts.back()->add_flags(XACT_VIRTUAL);
|
||||||
|
|
@ -437,9 +437,9 @@ void format_xml_entries::format_last_entry()
|
||||||
<< "</tr:date_eff>\n";
|
<< "</tr:date_eff>\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (xact->state == xact_t::CLEARED)
|
if (xact->state() == item_t::CLEARED)
|
||||||
out << " <tr:cleared/>\n";
|
out << " <tr:cleared/>\n";
|
||||||
else if (xact->state == xact_t::PENDING)
|
else if (xact->state() == xact_t::PENDING)
|
||||||
out << " <tr:pending/>\n";
|
out << " <tr:pending/>\n";
|
||||||
|
|
||||||
if (xact->has_flags(XACT_VIRTUAL))
|
if (xact->has_flags(XACT_VIRTUAL))
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue