Moved xact_xdata_t into xact_t itself, as a set of "extended data" that might
be gathered during reporting. Removed the references to accounts and such from the mask logic, which means that the value expression "acount =~ /foo/" is needed in place of just "/foo/".
This commit is contained in:
parent
7b3c8c03c5
commit
5a90fe7357
19 changed files with 386 additions and 386 deletions
7
csv.cc
7
csv.cc
|
|
@ -19,9 +19,8 @@ namespace {
|
||||||
|
|
||||||
void format_csv_xacts::operator()(xact_t& xact)
|
void format_csv_xacts::operator()(xact_t& xact)
|
||||||
{
|
{
|
||||||
if (! xact_has_xdata(xact) ||
|
if (! xact.has_xdata() ||
|
||||||
! (xact_xdata_(xact).dflags & XACT_DISPLAYED)) {
|
! xact.xdata().has_flags(XACT_EXT_DISPLAYED)) {
|
||||||
|
|
||||||
{
|
{
|
||||||
format_t fmt("%D");
|
format_t fmt("%D");
|
||||||
std::ostringstream str;
|
std::ostringstream str;
|
||||||
|
|
@ -111,7 +110,7 @@ void format_csv_xacts::operator()(xact_t& xact)
|
||||||
}
|
}
|
||||||
out << '\n';
|
out << '\n';
|
||||||
|
|
||||||
xact_xdata(xact).dflags |= XACT_DISPLAYED;
|
xact.xdata().add_flags(XACT_EXT_DISPLAYED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
8
emacs.cc
8
emacs.cc
|
|
@ -33,8 +33,8 @@ void format_emacs_xacts::write_entry(entry_t& entry)
|
||||||
|
|
||||||
void format_emacs_xacts::operator()(xact_t& xact)
|
void format_emacs_xacts::operator()(xact_t& xact)
|
||||||
{
|
{
|
||||||
if (! xact_has_xdata(xact) ||
|
if (! xact.has_xdata() ||
|
||||||
! (xact_xdata_(xact).dflags & XACT_DISPLAYED)) {
|
! xact.xdata().has_flags(XACT_EXT_DISPLAYED)) {
|
||||||
if (! last_entry) {
|
if (! last_entry) {
|
||||||
out << "((";
|
out << "((";
|
||||||
write_entry(*xact.entry);
|
write_entry(*xact.entry);
|
||||||
|
|
@ -48,7 +48,7 @@ void format_emacs_xacts::operator()(xact_t& xact)
|
||||||
}
|
}
|
||||||
|
|
||||||
out << " (" << (static_cast<unsigned long>(xact.beg_line) + 1) << " ";
|
out << " (" << (static_cast<unsigned long>(xact.beg_line) + 1) << " ";
|
||||||
out << "\"" << xact_account(xact)->fullname() << "\" \""
|
out << "\"" << xact.reported_account()->fullname() << "\" \""
|
||||||
<< xact.amount << "\"";
|
<< xact.amount << "\"";
|
||||||
|
|
||||||
switch (xact.state) {
|
switch (xact.state) {
|
||||||
|
|
@ -71,7 +71,7 @@ void format_emacs_xacts::operator()(xact_t& xact)
|
||||||
|
|
||||||
last_entry = xact.entry;
|
last_entry = xact.entry;
|
||||||
|
|
||||||
xact_xdata(xact).dflags |= XACT_DISPLAYED;
|
xact.xdata().add_flags(XACT_EXT_DISPLAYED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
6
entry.h
6
entry.h
|
|
@ -39,8 +39,6 @@ namespace ledger {
|
||||||
|
|
||||||
class journal_t;
|
class journal_t;
|
||||||
|
|
||||||
typedef std::list<xact_t *> xacts_list;
|
|
||||||
|
|
||||||
class entry_base_t : public supports_flags<>
|
class entry_base_t : public supports_flags<>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -232,6 +230,10 @@ inline bool auto_entry_finalizer_t::operator()(entry_t& entry, bool post) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef std::list<entry_t *> entries_list;
|
||||||
|
typedef std::list<auto_entry_t *> auto_entries_list;
|
||||||
|
typedef std::list<period_entry_t *> period_entries_list;
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
||||||
#endif // _ENTRY_H
|
#endif // _ENTRY_H
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,6 @@ typedef std::list<path> paths_list;
|
||||||
class session_t;
|
class session_t;
|
||||||
class account_t;
|
class account_t;
|
||||||
|
|
||||||
typedef std::list<entry_t *> entries_list;
|
|
||||||
typedef std::list<auto_entry_t *> auto_entries_list;
|
|
||||||
typedef std::list<period_entry_t *> period_entries_list;
|
|
||||||
|
|
||||||
class journal_t : public noncopyable
|
class journal_t : public noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
12
mask.h
12
mask.h
|
|
@ -36,25 +36,17 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
class mask_t : public supports_flags<>
|
class mask_t
|
||||||
{
|
{
|
||||||
mask_t();
|
mask_t();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#define MASK_SHORT_ACCOUNT 0x01
|
|
||||||
#define MASK_CODE 0x02
|
|
||||||
#define MASK_COMMODITY 0x04
|
|
||||||
#define MASK_PAYEE 0x08
|
|
||||||
#define MASK_NOTE 0x10
|
|
||||||
#define MASK_ACCOUNT 0x20
|
|
||||||
|
|
||||||
bool exclude;
|
bool exclude;
|
||||||
boost::regex expr;
|
boost::regex expr;
|
||||||
|
|
||||||
explicit mask_t(const string& pattern);
|
explicit mask_t(const string& pattern);
|
||||||
|
|
||||||
mask_t(const mask_t& m)
|
mask_t(const mask_t& m) : exclude(m.exclude), expr(m.expr) {
|
||||||
: supports_flags<>(), exclude(m.exclude), expr(m.expr) {
|
|
||||||
TRACE_CTOR(mask_t, "copy");
|
TRACE_CTOR(mask_t, "copy");
|
||||||
}
|
}
|
||||||
~mask_t() throw() {
|
~mask_t() throw() {
|
||||||
|
|
|
||||||
28
op.cc
28
op.cc
|
|
@ -647,34 +647,6 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope)
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
case MASK: {
|
|
||||||
ptr_op_t match = new op_t(op_t::O_MATCH);
|
|
||||||
match->set_right(this);
|
|
||||||
|
|
||||||
// jww (2008-08-02): Coupling!
|
|
||||||
ptr_op_t ident = new op_t(op_t::IDENT);
|
|
||||||
switch (as_mask().flags()) {
|
|
||||||
case MASK_SHORT_ACCOUNT:
|
|
||||||
ident->set_ident("account_base");
|
|
||||||
break;
|
|
||||||
case MASK_CODE:
|
|
||||||
ident->set_ident("code");
|
|
||||||
break;
|
|
||||||
case MASK_PAYEE:
|
|
||||||
ident->set_ident("payee");
|
|
||||||
break;
|
|
||||||
case MASK_NOTE:
|
|
||||||
ident->set_ident("note");
|
|
||||||
break;
|
|
||||||
case MASK_ACCOUNT:
|
|
||||||
ident->set_ident("account");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
match->set_left(ident->compile(scope));
|
|
||||||
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@ expr_t::parser_t::parse_value_term(std::istream& in,
|
||||||
case token_t::MASK:
|
case token_t::MASK:
|
||||||
node = new op_t(op_t::MASK);
|
node = new op_t(op_t::MASK);
|
||||||
node->set_mask(tok.value.as_string());
|
node->set_mask(tok.value.as_string());
|
||||||
node->as_mask_lval().add_flags(tok.flags());
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case token_t::IDENT: {
|
case token_t::IDENT: {
|
||||||
|
|
|
||||||
10
parser.h
10
parser.h
|
|
@ -46,10 +46,14 @@ class expr_t::parser_t : public noncopyable
|
||||||
#define EXPR_PARSE_NO_ASSIGN 0x08
|
#define EXPR_PARSE_NO_ASSIGN 0x08
|
||||||
#define EXPR_PARSE_NO_DATES 0x10
|
#define EXPR_PARSE_NO_DATES 0x10
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef uint_least8_t flags_t;
|
||||||
|
|
||||||
|
private:
|
||||||
mutable token_t lookahead;
|
mutable token_t lookahead;
|
||||||
mutable bool use_lookahead;
|
mutable bool use_lookahead;
|
||||||
|
|
||||||
token_t& next_token(std::istream& in, token_t::flags_t tflags) const
|
token_t& next_token(std::istream& in, flags_t tflags) const
|
||||||
{
|
{
|
||||||
if (use_lookahead)
|
if (use_lookahead)
|
||||||
use_lookahead = false;
|
use_lookahead = false;
|
||||||
|
|
@ -69,10 +73,6 @@ class expr_t::parser_t : public noncopyable
|
||||||
use_lookahead = true;
|
use_lookahead = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
typedef uint_least8_t flags_t;
|
|
||||||
|
|
||||||
private:
|
|
||||||
ptr_op_t parse_value_term(std::istream& in, const flags_t flags) const;
|
ptr_op_t parse_value_term(std::istream& in, const flags_t flags) const;
|
||||||
ptr_op_t parse_unary_expr(std::istream& in, const flags_t flags) const;
|
ptr_op_t parse_unary_expr(std::istream& in, const flags_t flags) const;
|
||||||
ptr_op_t parse_mul_expr(std::istream& in, const flags_t flags) const;
|
ptr_op_t parse_mul_expr(std::istream& in, const flags_t flags) const;
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
#define xact_next(x) reinterpret_cast<xact_t *>(xact_xdata(*x).ptr)
|
#define xact_next(x) reinterpret_cast<xact_t *>(x->xdata().ptr)
|
||||||
#define xact_next_ptr(x) reinterpret_cast<xact_t **>(&xact_xdata(*x).ptr)
|
#define xact_next_ptr(x) reinterpret_cast<xact_t **>(&x->xdata().ptr)
|
||||||
|
|
||||||
static bool search_for_balance(amount_t& amount,
|
static bool search_for_balance(amount_t& amount,
|
||||||
xact_t ** prev, xact_t * next)
|
xact_t ** prev, xact_t * next)
|
||||||
|
|
|
||||||
|
|
@ -476,8 +476,8 @@ format_xacts::format_xacts(std::ostream& _output_stream,
|
||||||
|
|
||||||
void format_xacts::operator()(xact_t& xact)
|
void format_xacts::operator()(xact_t& xact)
|
||||||
{
|
{
|
||||||
if (! xact_has_xdata(xact) ||
|
if (! xact.has_xdata() ||
|
||||||
! (xact_xdata_(xact).dflags & XACT_DISPLAYED)) {
|
! xact.xdata().has_flags(XACT_EXT_DISPLAYED)) {
|
||||||
if (last_entry != xact.entry) {
|
if (last_entry != xact.entry) {
|
||||||
first_line_format.format(output_stream, xact);
|
first_line_format.format(output_stream, xact);
|
||||||
last_entry = xact.entry;
|
last_entry = xact.entry;
|
||||||
|
|
@ -489,7 +489,7 @@ void format_xacts::operator()(xact_t& xact)
|
||||||
next_lines_format.format(output_stream, xact);
|
next_lines_format.format(output_stream, xact);
|
||||||
}
|
}
|
||||||
|
|
||||||
xact_xdata(xact).dflags |= XACT_DISPLAYED;
|
xact.xdata().add_flags(XACT_EXT_DISPLAYED);
|
||||||
last_xact = &xact;
|
last_xact = &xact;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -515,7 +515,7 @@ void format_entries::format_last_entry()
|
||||||
|
|
||||||
void format_entries::operator()(xact_t& xact)
|
void format_entries::operator()(xact_t& xact)
|
||||||
{
|
{
|
||||||
xact_xdata(xact).dflags |= XACT_TO_DISPLAY;
|
xact.xdata().add_flags(XACT_EXT_TO_DISPLAY);
|
||||||
|
|
||||||
if (last_entry && xact.entry != last_entry)
|
if (last_entry && xact.entry != last_entry)
|
||||||
format_last_entry();
|
format_last_entry();
|
||||||
|
|
|
||||||
|
|
@ -1079,7 +1079,7 @@ void write_textual_journal(journal_t& journal,
|
||||||
if (base) {
|
if (base) {
|
||||||
foreach (xact_t * xact, base->xacts) {
|
foreach (xact_t * xact, base->xacts) {
|
||||||
if (! xact->has_flags(XACT_AUTO)) {
|
if (! xact->has_flags(XACT_AUTO)) {
|
||||||
xact_xdata(*xact).dflags |= XACT_TO_DISPLAY;
|
xact->xdata().add_flags(XACT_EXT_TO_DISPLAY);
|
||||||
(*formatter)(*xact);
|
(*formatter)(*xact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
token.cc
17
token.cc
|
|
@ -53,8 +53,6 @@ void expr_t::token_t::parse_ident(std::istream& in)
|
||||||
kind = IDENT;
|
kind = IDENT;
|
||||||
length = 0;
|
length = 0;
|
||||||
|
|
||||||
clear_flags();
|
|
||||||
|
|
||||||
char buf[256];
|
char buf[256];
|
||||||
READ_INTO_(in, buf, 255, c, length,
|
READ_INTO_(in, buf, 255, c, length,
|
||||||
std::isalnum(c) || c == '_' || c == '.' || c == '-');
|
std::isalnum(c) || c == '_' || c == '.' || c == '-');
|
||||||
|
|
@ -122,7 +120,7 @@ void expr_t::token_t::parse_ident(std::istream& in)
|
||||||
value.set_string(buf);
|
value.set_string(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void expr_t::token_t::next(std::istream& in, const unsigned int pflags)
|
void expr_t::token_t::next(std::istream& in, const uint_least8_t pflags)
|
||||||
{
|
{
|
||||||
if (in.eof()) {
|
if (in.eof()) {
|
||||||
kind = TOK_EOF;
|
kind = TOK_EOF;
|
||||||
|
|
@ -284,19 +282,6 @@ void expr_t::token_t::next(std::istream& in, const unsigned int pflags)
|
||||||
in.get(c);
|
in.get(c);
|
||||||
length++;
|
length++;
|
||||||
|
|
||||||
if (short_account_mask)
|
|
||||||
set_flags(MASK_SHORT_ACCOUNT);
|
|
||||||
else if (code_mask)
|
|
||||||
set_flags(MASK_CODE);
|
|
||||||
else if (commodity_mask)
|
|
||||||
set_flags(MASK_COMMODITY);
|
|
||||||
else if (payee_mask)
|
|
||||||
set_flags(MASK_PAYEE);
|
|
||||||
else if (note_mask)
|
|
||||||
set_flags(MASK_NOTE);
|
|
||||||
else
|
|
||||||
set_flags(MASK_ACCOUNT);
|
|
||||||
|
|
||||||
kind = MASK;
|
kind = MASK;
|
||||||
value.set_string(buf);
|
value.set_string(buf);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
6
token.h
6
token.h
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
struct expr_t::token_t : public noncopyable, public supports_flags<>
|
struct expr_t::token_t : public noncopyable
|
||||||
{
|
{
|
||||||
enum kind_t {
|
enum kind_t {
|
||||||
VALUE, // any kind of literal value
|
VALUE, // any kind of literal value
|
||||||
|
|
@ -79,7 +79,7 @@ struct expr_t::token_t : public noncopyable, public supports_flags<>
|
||||||
value_t value;
|
value_t value;
|
||||||
std::size_t length;
|
std::size_t length;
|
||||||
|
|
||||||
explicit token_t() : supports_flags<>(), kind(UNKNOWN), length(0) {
|
explicit token_t() : kind(UNKNOWN), length(0) {
|
||||||
TRACE_CTOR(token_t, "");
|
TRACE_CTOR(token_t, "");
|
||||||
}
|
}
|
||||||
~token_t() throw() {
|
~token_t() throw() {
|
||||||
|
|
@ -104,7 +104,7 @@ struct expr_t::token_t : public noncopyable, public supports_flags<>
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_ident(std::istream& in);
|
void parse_ident(std::istream& in);
|
||||||
void next(std::istream& in, unsigned int flags);
|
void next(std::istream& in, const uint_least8_t flags);
|
||||||
void rewind(std::istream& in);
|
void rewind(std::istream& in);
|
||||||
void unexpected();
|
void unexpected();
|
||||||
|
|
||||||
|
|
|
||||||
151
walk.cc
151
walk.cc
|
|
@ -8,24 +8,23 @@
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool compare_items<xact_t>::operator()(const xact_t * left,
|
bool compare_items<xact_t>::operator()(xact_t * left, xact_t * right)
|
||||||
const xact_t * right)
|
|
||||||
{
|
{
|
||||||
assert(left);
|
assert(left);
|
||||||
assert(right);
|
assert(right);
|
||||||
|
|
||||||
xact_xdata_t& lxdata(xact_xdata(*left));
|
xact_t::xdata_t& lxdata(left->xdata());
|
||||||
if (! (lxdata.dflags & XACT_SORT_CALC)) {
|
if (! lxdata.has_flags(XACT_EXT_SORT_CALC)) {
|
||||||
lxdata.sort_value = sort_order.calc(const_cast<xact_t&>(*left));
|
lxdata.sort_value = sort_order.calc(*left);
|
||||||
lxdata.sort_value.reduce();
|
lxdata.sort_value.reduce();
|
||||||
lxdata.dflags |= XACT_SORT_CALC;
|
lxdata.add_flags(XACT_EXT_SORT_CALC);
|
||||||
}
|
}
|
||||||
|
|
||||||
xact_xdata_t& rxdata(xact_xdata(*right));
|
xact_t::xdata_t& rxdata(right->xdata());
|
||||||
if (! (rxdata.dflags & XACT_SORT_CALC)) {
|
if (! rxdata.has_flags(XACT_EXT_SORT_CALC)) {
|
||||||
rxdata.sort_value = sort_order.calc(const_cast<xact_t&>(*right));
|
rxdata.sort_value = sort_order.calc(*right);
|
||||||
rxdata.sort_value.reduce();
|
rxdata.sort_value.reduce();
|
||||||
rxdata.dflags |= XACT_SORT_CALC;
|
rxdata.add_flags(XACT_EXT_SORT_CALC);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG("ledger.walk.compare_items_xact",
|
DEBUG("ledger.walk.compare_items_xact",
|
||||||
|
|
@ -36,27 +35,6 @@ bool compare_items<xact_t>::operator()(const xact_t * left,
|
||||||
return lxdata.sort_value < rxdata.sort_value;
|
return lxdata.sort_value < rxdata.sort_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
xact_xdata_t& xact_xdata(const xact_t& xact)
|
|
||||||
{
|
|
||||||
if (! xact.data)
|
|
||||||
xact.data = new xact_xdata_t();
|
|
||||||
return *static_cast<xact_xdata_t *>(xact.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_xact_to(const xact_t& xact, value_t& value)
|
|
||||||
{
|
|
||||||
if (xact_has_xdata(xact) &&
|
|
||||||
xact_xdata_(xact).dflags & XACT_COMPOUND) {
|
|
||||||
value += xact_xdata_(xact).value;
|
|
||||||
}
|
|
||||||
else if (xact.cost || (! value.is_null() && ! value.is_realzero())) {
|
|
||||||
value.add(xact.amount, xact.cost);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
value = xact.amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void entries_iterator::reset(session_t& session)
|
void entries_iterator::reset(session_t& session)
|
||||||
{
|
{
|
||||||
journals_i = session.journals.begin();
|
journals_i = session.journals.begin();
|
||||||
|
|
@ -157,11 +135,11 @@ void truncate_entries::flush()
|
||||||
|
|
||||||
void set_account_value::operator()(xact_t& xact)
|
void set_account_value::operator()(xact_t& xact)
|
||||||
{
|
{
|
||||||
account_t * acct = xact_account(xact);
|
account_t * acct = xact.reported_account();
|
||||||
assert(acct);
|
assert(acct);
|
||||||
|
|
||||||
account_xdata_t& xdata = account_xdata(*acct);
|
account_xdata_t& xdata = account_xdata(*acct);
|
||||||
add_xact_to(xact, xdata.value);
|
xact.add_to_value(xdata.value);
|
||||||
|
|
||||||
xdata.count++;
|
xdata.count++;
|
||||||
if (xact.has_flags(XACT_VIRTUAL))
|
if (xact.has_flags(XACT_VIRTUAL))
|
||||||
|
|
@ -176,7 +154,7 @@ void sort_xacts::post_accumulated_xacts()
|
||||||
compare_items<xact_t>(sort_order));
|
compare_items<xact_t>(sort_order));
|
||||||
|
|
||||||
foreach (xact_t * xact, xacts) {
|
foreach (xact_t * xact, xacts) {
|
||||||
xact_xdata(*xact).dflags &= ~XACT_SORT_CALC;
|
xact->xdata().drop_flags(XACT_EXT_SORT_CALC);
|
||||||
item_handler<xact_t>::operator()(*xact);
|
item_handler<xact_t>::operator()(*xact);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -186,26 +164,24 @@ void sort_xacts::post_accumulated_xacts()
|
||||||
void calc_xacts::operator()(xact_t& xact)
|
void calc_xacts::operator()(xact_t& xact)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
xact_t::xdata_t& xdata(xact.xdata());
|
||||||
|
|
||||||
xact_xdata_t& xdata(xact_xdata(xact));
|
if (last_xact && last_xact->has_xdata()) {
|
||||||
|
|
||||||
if (last_xact && xact_has_xdata(*last_xact)) {
|
|
||||||
if (xdata.total.is_null())
|
if (xdata.total.is_null())
|
||||||
xdata.total = xact_xdata_(*last_xact).total;
|
xdata.total = last_xact->xdata().total;
|
||||||
else
|
else
|
||||||
xdata.total += xact_xdata_(*last_xact).total;
|
xdata.total += last_xact->xdata().total;
|
||||||
xdata.index = xact_xdata_(*last_xact).index + 1;
|
xdata.index = last_xact->xdata().index + 1;
|
||||||
} else {
|
} else {
|
||||||
xdata.index = 0;
|
xdata.index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! (xdata.dflags & XACT_NO_TOTAL))
|
if (! xdata.has_flags(XACT_EXT_NO_TOTAL))
|
||||||
add_xact_to(xact, xdata.total);
|
xact.add_to_value(xdata.total);
|
||||||
|
|
||||||
item_handler<xact_t>::operator()(xact);
|
item_handler<xact_t>::operator()(xact);
|
||||||
|
|
||||||
last_xact = &xact;
|
last_xact = &xact;
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (const std::exception& err) {
|
catch (const std::exception& err) {
|
||||||
add_error_context("Calculating transaction at");
|
add_error_context("Calculating transaction at");
|
||||||
|
|
@ -218,9 +194,9 @@ void calc_xacts::operator()(xact_t& xact)
|
||||||
|
|
||||||
void invert_xacts::operator()(xact_t& xact)
|
void invert_xacts::operator()(xact_t& xact)
|
||||||
{
|
{
|
||||||
if (xact_has_xdata(xact) &&
|
if (xact.has_xdata() &&
|
||||||
xact_xdata_(xact).dflags & XACT_COMPOUND) {
|
xact.xdata().has_flags(XACT_EXT_COMPOUND)) {
|
||||||
xact_xdata_(xact).value.negate();
|
xact.xdata().value.negate();
|
||||||
} else {
|
} else {
|
||||||
xact.amount.negate();
|
xact.amount.negate();
|
||||||
if (xact.cost)
|
if (xact.cost)
|
||||||
|
|
@ -251,7 +227,7 @@ void handle_value(const value_t& value,
|
||||||
// temporary, do so now.
|
// temporary, do so now.
|
||||||
|
|
||||||
if (component_xacts)
|
if (component_xacts)
|
||||||
xact_xdata(xact).copy_component_xacts(*component_xacts);
|
xact.xdata().copy_component_xacts(*component_xacts);
|
||||||
|
|
||||||
// If the account for this xact is all virtual, then report
|
// If the account for this xact is all virtual, then report
|
||||||
// the xact as such. This allows subtotal reports to show
|
// the xact as such. This allows subtotal reports to show
|
||||||
|
|
@ -264,7 +240,7 @@ void handle_value(const value_t& value,
|
||||||
xact.add_flags(XACT_BALANCE);
|
xact.add_flags(XACT_BALANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
xact_xdata_t& xdata(xact_xdata(xact));
|
xact_t::xdata_t& xdata(xact.xdata());
|
||||||
|
|
||||||
if (is_valid(date))
|
if (is_valid(date))
|
||||||
xdata.date = date;
|
xdata.date = date;
|
||||||
|
|
@ -286,7 +262,7 @@ void handle_value(const value_t& value,
|
||||||
case value_t::BALANCE:
|
case value_t::BALANCE:
|
||||||
case value_t::BALANCE_PAIR:
|
case value_t::BALANCE_PAIR:
|
||||||
xdata.value = temp;
|
xdata.value = temp;
|
||||||
flags |= XACT_COMPOUND;
|
flags |= XACT_EXT_COMPOUND;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -295,7 +271,7 @@ void handle_value(const value_t& value,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags)
|
if (flags)
|
||||||
xdata.dflags |= flags;
|
xdata.add_flags(flags);
|
||||||
|
|
||||||
handler(xact);
|
handler(xact);
|
||||||
}
|
}
|
||||||
|
|
@ -330,7 +306,7 @@ void collapse_xacts::operator()(xact_t& xact)
|
||||||
if (last_entry && last_entry != xact.entry && count > 0)
|
if (last_entry && last_entry != xact.entry && count > 0)
|
||||||
report_subtotal();
|
report_subtotal();
|
||||||
|
|
||||||
add_xact_to(xact, subtotal);
|
xact.add_to_value(subtotal);
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
last_entry = xact.entry;
|
last_entry = xact.entry;
|
||||||
|
|
@ -343,12 +319,12 @@ void related_xacts::flush()
|
||||||
foreach (xact_t * xact, xacts) {
|
foreach (xact_t * xact, xacts) {
|
||||||
if (xact->entry) {
|
if (xact->entry) {
|
||||||
foreach (xact_t * r_xact, xact->entry->xacts) {
|
foreach (xact_t * r_xact, xact->entry->xacts) {
|
||||||
xact_xdata_t& xdata = xact_xdata(*r_xact);
|
xact_t::xdata_t& xdata(r_xact->xdata());
|
||||||
if (! (xdata.dflags & XACT_HANDLED) &&
|
if (! xdata.has_flags(XACT_EXT_HANDLED) &&
|
||||||
(! (xdata.dflags & XACT_RECEIVED) ?
|
(! xdata.has_flags(XACT_EXT_RECEIVED) ?
|
||||||
! r_xact->has_flags(XACT_AUTO | XACT_VIRTUAL) :
|
! r_xact->has_flags(XACT_AUTO | XACT_VIRTUAL) :
|
||||||
also_matching)) {
|
also_matching)) {
|
||||||
xdata.dflags |= XACT_HANDLED;
|
xdata.add_flags(XACT_EXT_HANDLED);
|
||||||
item_handler<xact_t>::operator()(*r_xact);
|
item_handler<xact_t>::operator()(*r_xact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -356,10 +332,10 @@ void related_xacts::flush()
|
||||||
// This code should only be reachable from the "output"
|
// This code should only be reachable from the "output"
|
||||||
// command, since that is the only command which attempts to
|
// command, since that is the only command which attempts to
|
||||||
// output auto or period entries.
|
// output auto or period entries.
|
||||||
xact_xdata_t& xdata = xact_xdata(*xact);
|
xact_t::xdata_t& xdata(xact->xdata());
|
||||||
if (! (xdata.dflags & XACT_HANDLED) &&
|
if (! xdata.has_flags(XACT_EXT_HANDLED) &&
|
||||||
! xact->has_flags(XACT_AUTO)) {
|
! xact->has_flags(XACT_AUTO)) {
|
||||||
xdata.dflags |= XACT_HANDLED;
|
xdata.add_flags(XACT_EXT_HANDLED);
|
||||||
item_handler<xact_t>::operator()(*xact);
|
item_handler<xact_t>::operator()(*xact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -373,7 +349,7 @@ void changed_value_xacts::output_diff(const date_t& date)
|
||||||
{
|
{
|
||||||
value_t cur_bal;
|
value_t cur_bal;
|
||||||
|
|
||||||
xact_xdata(*last_xact).date = date;
|
last_xact->xdata().date = date;
|
||||||
#if 0
|
#if 0
|
||||||
compute_total(cur_bal, details_t(*last_xact));
|
compute_total(cur_bal, details_t(*last_xact));
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -381,7 +357,7 @@ void changed_value_xacts::output_diff(const date_t& date)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// jww (2008-04-24): What does this do?
|
// jww (2008-04-24): What does this do?
|
||||||
xact_xdata(*last_xact).date = 0;
|
last_xact->xdata().date = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (value_t diff = cur_bal - last_balance) {
|
if (value_t diff = cur_bal - last_balance) {
|
||||||
|
|
@ -390,24 +366,18 @@ void changed_value_xacts::output_diff(const date_t& date)
|
||||||
entry.payee = "Commodities revalued";
|
entry.payee = "Commodities revalued";
|
||||||
entry._date = date;
|
entry._date = date;
|
||||||
|
|
||||||
handle_value(diff, NULL, &entry, XACT_NO_TOTAL, xact_temps,
|
handle_value(diff, NULL, &entry, XACT_EXT_NO_TOTAL, xact_temps,
|
||||||
*handler);
|
*handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void changed_value_xacts::operator()(xact_t& xact)
|
void changed_value_xacts::operator()(xact_t& xact)
|
||||||
{
|
{
|
||||||
if (last_xact) {
|
if (last_xact)
|
||||||
date_t date;
|
output_diff(last_xact->reported_date());
|
||||||
if (xact_has_xdata(*last_xact))
|
|
||||||
date = xact_xdata_(*last_xact).date;
|
|
||||||
else
|
|
||||||
date = xact.date();
|
|
||||||
output_diff(date);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed_values_only)
|
if (changed_values_only)
|
||||||
xact_xdata(xact).dflags |= XACT_DISPLAYED;
|
xact.xdata().add_flags(XACT_EXT_DISPLAYED);
|
||||||
|
|
||||||
item_handler<xact_t>::operator()(xact);
|
item_handler<xact_t>::operator()(xact);
|
||||||
|
|
||||||
|
|
@ -422,9 +392,13 @@ void changed_value_xacts::operator()(xact_t& xact)
|
||||||
void component_xacts::operator()(xact_t& xact)
|
void component_xacts::operator()(xact_t& xact)
|
||||||
{
|
{
|
||||||
if (handler && pred(xact)) {
|
if (handler && pred(xact)) {
|
||||||
if (xact_has_xdata(xact) &&
|
if (xact.has_xdata() &&
|
||||||
xact_xdata_(xact).have_component_xacts())
|
xact.xdata().has_component_xacts())
|
||||||
xact_xdata_(xact).walk_component_xacts(*handler);
|
#if 0
|
||||||
|
xact.xdata().walk_component_xacts(*handler);
|
||||||
|
#else
|
||||||
|
;
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
(*handler)(xact);
|
(*handler)(xact);
|
||||||
}
|
}
|
||||||
|
|
@ -460,13 +434,13 @@ void subtotal_xacts::operator()(xact_t& xact)
|
||||||
if (! is_valid(finish) || xact.date() > finish)
|
if (! is_valid(finish) || xact.date() > finish)
|
||||||
finish = xact.date();
|
finish = xact.date();
|
||||||
|
|
||||||
account_t * acct = xact_account(xact);
|
account_t * acct = xact.reported_account();
|
||||||
assert(acct);
|
assert(acct);
|
||||||
|
|
||||||
values_map::iterator i = values.find(acct->fullname());
|
values_map::iterator i = values.find(acct->fullname());
|
||||||
if (i == values.end()) {
|
if (i == values.end()) {
|
||||||
value_t temp;
|
value_t temp;
|
||||||
add_xact_to(xact, temp);
|
xact.add_to_value(temp);
|
||||||
std::pair<values_map::iterator, bool> result
|
std::pair<values_map::iterator, bool> result
|
||||||
= values.insert(values_pair(acct->fullname(), acct_value_t(acct, temp)));
|
= values.insert(values_pair(acct->fullname(), acct_value_t(acct, temp)));
|
||||||
assert(result.second);
|
assert(result.second);
|
||||||
|
|
@ -474,7 +448,7 @@ void subtotal_xacts::operator()(xact_t& xact)
|
||||||
if (remember_components)
|
if (remember_components)
|
||||||
(*result.first).second.components.push_back(&xact);
|
(*result.first).second.components.push_back(&xact);
|
||||||
} else {
|
} else {
|
||||||
add_xact_to(xact, (*i).second.value);
|
xact.add_to_value((*i).second.value);
|
||||||
|
|
||||||
if (remember_components)
|
if (remember_components)
|
||||||
(*i).second.components.push_back(&xact);
|
(*i).second.components.push_back(&xact);
|
||||||
|
|
@ -485,9 +459,9 @@ void subtotal_xacts::operator()(xact_t& xact)
|
||||||
// that contain only virtual xacts.
|
// that contain only virtual xacts.
|
||||||
|
|
||||||
if (! xact.has_flags(XACT_VIRTUAL))
|
if (! xact.has_flags(XACT_VIRTUAL))
|
||||||
account_xdata(*xact_account(xact)).dflags |= ACCOUNT_HAS_NON_VIRTUALS;
|
account_xdata(*xact.reported_account()).dflags |= ACCOUNT_HAS_NON_VIRTUALS;
|
||||||
else if (! xact.has_flags(XACT_BALANCE))
|
else if (! xact.has_flags(XACT_BALANCE))
|
||||||
account_xdata(*xact_account(xact)).dflags |= ACCOUNT_HAS_UNB_VIRTUALS;
|
account_xdata(*xact.reported_account()).dflags |= ACCOUNT_HAS_UNB_VIRTUALS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void interval_xacts::report_subtotal(const date_t& date)
|
void interval_xacts::report_subtotal(const date_t& date)
|
||||||
|
|
@ -675,7 +649,7 @@ void budget_xacts::report_budget_items(const date_t& date)
|
||||||
xact_t& xact = *pair.second;
|
xact_t& xact = *pair.second;
|
||||||
|
|
||||||
DEBUG("ledger.walk.budget", "Reporting budget for "
|
DEBUG("ledger.walk.budget", "Reporting budget for "
|
||||||
<< xact_account(xact)->fullname());
|
<< xact.reported_account()->fullname());
|
||||||
|
|
||||||
entry_temps.push_back(entry_t());
|
entry_temps.push_back(entry_t());
|
||||||
entry_t& entry = entry_temps.back();
|
entry_t& entry = entry_temps.back();
|
||||||
|
|
@ -704,15 +678,15 @@ void budget_xacts::operator()(xact_t& xact)
|
||||||
bool xact_in_budget = false;
|
bool xact_in_budget = false;
|
||||||
|
|
||||||
foreach (pending_xacts_list::value_type& pair, pending_xacts)
|
foreach (pending_xacts_list::value_type& pair, pending_xacts)
|
||||||
for (account_t * acct = xact_account(xact);
|
for (account_t * acct = xact.reported_account();
|
||||||
acct;
|
acct;
|
||||||
acct = acct->parent) {
|
acct = acct->parent) {
|
||||||
if (acct == xact_account(*pair.second)) {
|
if (acct == (*pair.second).reported_account()) {
|
||||||
xact_in_budget = true;
|
xact_in_budget = true;
|
||||||
// Report the xact as if it had occurred in the parent
|
// Report the xact as if it had occurred in the parent
|
||||||
// account.
|
// account.
|
||||||
if (xact_account(xact) != acct)
|
if (xact.reported_account() != acct)
|
||||||
xact_xdata(xact).account = acct;
|
xact.xdata().account = acct;
|
||||||
goto handle;
|
goto handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -782,8 +756,8 @@ void forecast_xacts::flush()
|
||||||
|
|
||||||
item_handler<xact_t>::operator()(temp);
|
item_handler<xact_t>::operator()(temp);
|
||||||
|
|
||||||
if (xact_has_xdata(temp) &&
|
if (temp.has_xdata() &&
|
||||||
xact_xdata_(temp).dflags & XACT_MATCHES) {
|
temp.xdata().has_flags(XACT_EXT_MATCHES)) {
|
||||||
if (! pred(temp))
|
if (! pred(temp))
|
||||||
break;
|
break;
|
||||||
last = temp.date();
|
last = temp.date();
|
||||||
|
|
@ -808,21 +782,20 @@ void forecast_xacts::flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool compare_items<account_t>::operator()(const account_t * left,
|
bool compare_items<account_t>::operator()(account_t * left, account_t * right)
|
||||||
const account_t * right)
|
|
||||||
{
|
{
|
||||||
assert(left);
|
assert(left);
|
||||||
assert(right);
|
assert(right);
|
||||||
|
|
||||||
account_xdata_t& lxdata(account_xdata(*left));
|
account_xdata_t& lxdata(account_xdata(*left));
|
||||||
if (! (lxdata.dflags & ACCOUNT_SORT_CALC)) {
|
if (! (lxdata.dflags & ACCOUNT_SORT_CALC)) {
|
||||||
lxdata.sort_value = sort_order.calc(const_cast<account_t&>(*left));
|
lxdata.sort_value = sort_order.calc(*left);
|
||||||
lxdata.dflags |= ACCOUNT_SORT_CALC;
|
lxdata.dflags |= ACCOUNT_SORT_CALC;
|
||||||
}
|
}
|
||||||
|
|
||||||
account_xdata_t& rxdata(account_xdata(*right));
|
account_xdata_t& rxdata(account_xdata(*right));
|
||||||
if (! (rxdata.dflags & ACCOUNT_SORT_CALC)) {
|
if (! (rxdata.dflags & ACCOUNT_SORT_CALC)) {
|
||||||
rxdata.sort_value = sort_order.calc(const_cast<account_t&>(*right));
|
rxdata.sort_value = sort_order.calc(*right);
|
||||||
rxdata.dflags |= ACCOUNT_SORT_CALC;
|
rxdata.dflags |= ACCOUNT_SORT_CALC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
213
walk.h
213
walk.h
|
|
@ -2,6 +2,7 @@
|
||||||
#define _WALK_H
|
#define _WALK_H
|
||||||
|
|
||||||
#include "journal.h"
|
#include "journal.h"
|
||||||
|
#include "entry.h"
|
||||||
#include "account.h"
|
#include "account.h"
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
@ -34,123 +35,6 @@ public:
|
||||||
|
|
||||||
typedef shared_ptr<item_handler<xact_t> > xact_handler_ptr;
|
typedef shared_ptr<item_handler<xact_t> > xact_handler_ptr;
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class compare_items
|
|
||||||
{
|
|
||||||
expr_t sort_order;
|
|
||||||
|
|
||||||
compare_items();
|
|
||||||
|
|
||||||
public:
|
|
||||||
compare_items(const compare_items& other) : sort_order(other.sort_order) {
|
|
||||||
TRACE_CTOR(compare_items, "copy");
|
|
||||||
}
|
|
||||||
compare_items(const expr_t& _sort_order) : sort_order(_sort_order) {
|
|
||||||
TRACE_CTOR(compare_items, "const value_expr&");
|
|
||||||
}
|
|
||||||
~compare_items() throw() {
|
|
||||||
TRACE_DTOR(compare_items);
|
|
||||||
}
|
|
||||||
bool operator()(const T * left, const T * right);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool compare_items<T>::operator()(const T * left, const T * right)
|
|
||||||
{
|
|
||||||
assert(left);
|
|
||||||
assert(right);
|
|
||||||
return sort_order.calc(*left) < sort_order.calc(*right);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
bool compare_items<xact_t>::operator()(const xact_t * left,
|
|
||||||
const xact_t * right);
|
|
||||||
template <>
|
|
||||||
bool compare_items<account_t>::operator()(const account_t * left,
|
|
||||||
const account_t * right);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Xact handlers
|
|
||||||
//
|
|
||||||
|
|
||||||
#define XACT_RECEIVED 0x0001
|
|
||||||
#define XACT_HANDLED 0x0002
|
|
||||||
#define XACT_TO_DISPLAY 0x0004
|
|
||||||
#define XACT_DISPLAYED 0x0008
|
|
||||||
#define XACT_NO_TOTAL 0x0010
|
|
||||||
#define XACT_SORT_CALC 0x0020
|
|
||||||
#define XACT_COMPOUND 0x0040
|
|
||||||
#define XACT_MATCHES 0x0080
|
|
||||||
|
|
||||||
struct xact_xdata_t : public noncopyable
|
|
||||||
{
|
|
||||||
value_t total;
|
|
||||||
value_t sort_value;
|
|
||||||
value_t value;
|
|
||||||
unsigned int index;
|
|
||||||
unsigned short dflags;
|
|
||||||
date_t date;
|
|
||||||
account_t * account;
|
|
||||||
void * ptr;
|
|
||||||
xacts_list * component_xacts;
|
|
||||||
|
|
||||||
xact_xdata_t()
|
|
||||||
: index(0), dflags(0),
|
|
||||||
account(NULL), ptr(NULL), component_xacts(NULL) {
|
|
||||||
TRACE_CTOR(xact_xdata_t, "");
|
|
||||||
}
|
|
||||||
~xact_xdata_t() {
|
|
||||||
TRACE_DTOR(xact_xdata_t);
|
|
||||||
if (component_xacts)
|
|
||||||
checked_delete(component_xacts);
|
|
||||||
}
|
|
||||||
|
|
||||||
void remember_xact(xact_t& xact) {
|
|
||||||
if (! component_xacts)
|
|
||||||
component_xacts = new xacts_list;
|
|
||||||
component_xacts->push_back(&xact);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool have_component_xacts() const {
|
|
||||||
return component_xacts != NULL && ! component_xacts->empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void copy_component_xacts(xacts_list& xacts) {
|
|
||||||
foreach (xact_t * xact, xacts)
|
|
||||||
remember_xact(*xact);
|
|
||||||
}
|
|
||||||
|
|
||||||
void walk_component_xacts(item_handler<xact_t>& handler) const {
|
|
||||||
foreach (xact_t * xact, *component_xacts)
|
|
||||||
handler(*xact);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool xact_has_xdata(const xact_t& xact) {
|
|
||||||
return xact.data != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline xact_xdata_t& xact_xdata_(const xact_t& xact) {
|
|
||||||
return *static_cast<xact_xdata_t *>(xact.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
xact_xdata_t& xact_xdata(const xact_t& xact);
|
|
||||||
void add_xact_to(const xact_t& xact, value_t& value);
|
|
||||||
|
|
||||||
inline account_t * xact_account(xact_t& xact) {
|
|
||||||
if (xact.data) {
|
|
||||||
account_t * account = xact_xdata(xact).account;
|
|
||||||
if (account)
|
|
||||||
return account;
|
|
||||||
}
|
|
||||||
return xact.account;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const account_t * xact_account(const xact_t& xact) {
|
|
||||||
return xact_account(const_cast<xact_t&>(xact));
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class entries_iterator : public noncopyable
|
class entries_iterator : public noncopyable
|
||||||
|
|
@ -258,10 +142,7 @@ class clear_xact_xdata : public item_handler<xact_t>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void operator()(xact_t& xact) {
|
virtual void operator()(xact_t& xact) {
|
||||||
if (xact.data) {
|
xact.clear_xdata();
|
||||||
checked_delete(static_cast<xact_xdata_t *>(xact.data));
|
|
||||||
xact.data = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -270,11 +151,11 @@ class pass_down_xacts : public item_handler<xact_t>
|
||||||
pass_down_xacts();
|
pass_down_xacts();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
pass_down_xacts(xact_handler_ptr handler,
|
pass_down_xacts(xact_handler_ptr handler, xacts_iterator& iter)
|
||||||
xacts_iterator& iter)
|
: item_handler<xact_t>(handler)
|
||||||
: item_handler<xact_t>(handler) {
|
{
|
||||||
TRACE_CTOR(pass_down_xacts,
|
TRACE_CTOR(pass_down_xacts, "xact_handler_ptr, xacts_iterator");
|
||||||
"xact_handler_ptr, xacts_iterator");
|
|
||||||
for (xact_t * xact = iter(); xact; xact = iter())
|
for (xact_t * xact = iter(); xact; xact = iter())
|
||||||
item_handler<xact_t>::operator()(*xact);
|
item_handler<xact_t>::operator()(*xact);
|
||||||
}
|
}
|
||||||
|
|
@ -284,6 +165,25 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class push_to_xacts_list : public item_handler<xact_t>
|
||||||
|
{
|
||||||
|
push_to_xacts_list();
|
||||||
|
|
||||||
|
public:
|
||||||
|
xacts_list& xacts;
|
||||||
|
|
||||||
|
push_to_xacts_list(xacts_list& _xacts) : xacts(_xacts) {
|
||||||
|
TRACE_CTOR(push_to_xacts_list, "xacts_list&");
|
||||||
|
}
|
||||||
|
virtual ~push_to_xacts_list() {
|
||||||
|
TRACE_DTOR(push_to_xacts_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void operator()(xact_t& xact) {
|
||||||
|
xacts.push_back(&xact);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class truncate_entries : public item_handler<xact_t>
|
class truncate_entries : public item_handler<xact_t>
|
||||||
{
|
{
|
||||||
int head_count;
|
int head_count;
|
||||||
|
|
@ -306,6 +206,9 @@ public:
|
||||||
|
|
||||||
virtual void flush();
|
virtual void flush();
|
||||||
virtual void operator()(xact_t& xact) {
|
virtual void operator()(xact_t& xact) {
|
||||||
|
if (tail_count == 0 && head_count > 0 &&
|
||||||
|
xacts.size() >= static_cast<unsigned int>(head_count))
|
||||||
|
return;
|
||||||
xacts.push_back(&xact);
|
xacts.push_back(&xact);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -319,26 +222,6 @@ public:
|
||||||
virtual void operator()(xact_t& xact);
|
virtual void operator()(xact_t& xact);
|
||||||
};
|
};
|
||||||
|
|
||||||
class push_to_xacts_list : public item_handler<xact_t>
|
|
||||||
{
|
|
||||||
push_to_xacts_list();
|
|
||||||
|
|
||||||
public:
|
|
||||||
xacts_list& xact_list;
|
|
||||||
|
|
||||||
push_to_xacts_list(xacts_list& _xact_list)
|
|
||||||
: xact_list(_xact_list) {
|
|
||||||
TRACE_CTOR(push_to_xacts_list, "xacts_list&");
|
|
||||||
}
|
|
||||||
virtual ~push_to_xacts_list() {
|
|
||||||
TRACE_DTOR(push_to_xacts_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void operator()(xact_t& xact) {
|
|
||||||
xact_list.push_back(&xact);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class sort_xacts : public item_handler<xact_t>
|
class sort_xacts : public item_handler<xact_t>
|
||||||
{
|
{
|
||||||
typedef std::deque<xact_t *> xacts_deque;
|
typedef std::deque<xact_t *> xacts_deque;
|
||||||
|
|
@ -444,7 +327,7 @@ public:
|
||||||
|
|
||||||
virtual void operator()(xact_t& xact) {
|
virtual void operator()(xact_t& xact) {
|
||||||
if (pred(xact)) {
|
if (pred(xact)) {
|
||||||
xact_xdata(xact).dflags |= XACT_MATCHES;
|
xact.xdata().add_flags(XACT_EXT_MATCHES);
|
||||||
(*handler)(xact);
|
(*handler)(xact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -567,7 +450,7 @@ public:
|
||||||
|
|
||||||
virtual void flush();
|
virtual void flush();
|
||||||
virtual void operator()(xact_t& xact) {
|
virtual void operator()(xact_t& xact) {
|
||||||
xact_xdata(xact).dflags |= XACT_RECEIVED;
|
xact.xdata().add_flags(XACT_EXT_RECEIVED);
|
||||||
xacts.push_back(&xact);
|
xacts.push_back(&xact);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1045,6 +928,40 @@ public:
|
||||||
virtual journal_t * operator()();
|
virtual journal_t * operator()();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class compare_items
|
||||||
|
{
|
||||||
|
expr_t sort_order;
|
||||||
|
|
||||||
|
compare_items();
|
||||||
|
|
||||||
|
public:
|
||||||
|
compare_items(const compare_items& other) : sort_order(other.sort_order) {
|
||||||
|
TRACE_CTOR(compare_items, "copy");
|
||||||
|
}
|
||||||
|
compare_items(const expr_t& _sort_order) : sort_order(_sort_order) {
|
||||||
|
TRACE_CTOR(compare_items, "const value_expr&");
|
||||||
|
}
|
||||||
|
~compare_items() throw() {
|
||||||
|
TRACE_DTOR(compare_items);
|
||||||
|
}
|
||||||
|
bool operator()(T * left, T * right);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool compare_items<T>::operator()(T * left, T * right)
|
||||||
|
{
|
||||||
|
assert(left);
|
||||||
|
assert(right);
|
||||||
|
return sort_order.calc(*left) < sort_order.calc(*right);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
bool compare_items<xact_t>::operator()(xact_t * left, xact_t * right);
|
||||||
|
template <>
|
||||||
|
bool compare_items<account_t>::operator()(account_t * left,
|
||||||
|
account_t * right);
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
||||||
#endif // _WALK_H
|
#endif // _WALK_H
|
||||||
|
|
|
||||||
98
xact.cc
98
xact.cc
|
|
@ -58,18 +58,39 @@ date_t xact_t::effective_date() const
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
value_t get_amount(xact_t& xact)
|
value_t get_state(xact_t& xact) {
|
||||||
{
|
return long(xact.state);
|
||||||
return xact.amount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t get_date(xact_t& xact)
|
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();
|
return xact.date();
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t get_account(call_scope_t& scope)
|
value_t get_amount(xact_t& xact) {
|
||||||
{
|
return xact.amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t get_cost(xact_t& xact) {
|
||||||
|
return xact.cost ? *xact.cost : xact.amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t get_note(xact_t& xact) {
|
||||||
|
return string_value(xact.note ? *xact.note : ":NOTELESS:");
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t get_account(call_scope_t& scope) {
|
||||||
xact_t& xact(downcast<xact_t>(*scope.parent));
|
xact_t& xact(downcast<xact_t>(*scope.parent));
|
||||||
|
|
||||||
long width = 0;
|
long width = 0;
|
||||||
|
|
@ -78,7 +99,7 @@ namespace {
|
||||||
|
|
||||||
// jww (2008-08-02): Accept a width here so that we can abbreviate the
|
// jww (2008-08-02): Accept a width here so that we can abbreviate the
|
||||||
// string.
|
// string.
|
||||||
string name = xact.account->fullname();
|
string name = xact.reported_account()->fullname();
|
||||||
|
|
||||||
if (width > 2)
|
if (width > 2)
|
||||||
name = format_t::truncate(name, width - 2, true);
|
name = format_t::truncate(name, width - 2, true);
|
||||||
|
|
@ -92,10 +113,33 @@ namespace {
|
||||||
return string_value(name);
|
return string_value(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t get_account_base(xact_t& xact)
|
value_t get_account_base(xact_t& xact) {
|
||||||
{
|
return string_value(xact.reported_account()->name);
|
||||||
assert(false);
|
}
|
||||||
return NULL_VALUE;
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// xdata_t members...
|
||||||
|
|
||||||
|
value_t get_total(xact_t& xact) {
|
||||||
|
if (xact.xdata_)
|
||||||
|
return xact.xdata_->total;
|
||||||
|
else
|
||||||
|
return xact.amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <value_t (*Func)(xact_t&)>
|
template <value_t (*Func)(xact_t&)>
|
||||||
|
|
@ -115,16 +159,33 @@ expr_t::ptr_op_t xact_t::lookup(const string& name)
|
||||||
else if (name == "account_base")
|
else if (name == "account_base")
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_account_base>);
|
return WRAP_FUNCTOR(get_wrapper<&get_account_base>);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
if (name == "cleared")
|
||||||
|
return expr_t::op_t::wrap_value(0L);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
if (name[1] == '\0' || name == "date")
|
if (name[1] == '\0' || name == "date")
|
||||||
return WRAP_FUNCTOR(get_wrapper<&get_date>);
|
return WRAP_FUNCTOR(get_wrapper<&get_date>);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
if (name.find("fmt_") == 0) {
|
if (name.find("fmt_") == 0) {
|
||||||
if (name == "fmt_A")
|
if (name == "fmt_A")
|
||||||
return WRAP_FUNCTOR(get_account);
|
return WRAP_FUNCTOR(get_account);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
if (name == "pending")
|
||||||
|
return expr_t::op_t::wrap_value(2L);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
if (name == "uncleared")
|
||||||
|
return expr_t::op_t::wrap_value(1L);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return entry->lookup(name);
|
return entry->lookup(name);
|
||||||
}
|
}
|
||||||
|
|
@ -187,4 +248,17 @@ xact_context::xact_context(const xact_t& _xact, const string& desc) throw()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void xact_t::add_to_value(value_t& value)
|
||||||
|
{
|
||||||
|
if (xdata_ && xdata_->has_flags(XACT_EXT_COMPOUND)) {
|
||||||
|
value += xdata_->value;
|
||||||
|
}
|
||||||
|
else if (cost || (! value.is_null() && ! value.is_realzero())) {
|
||||||
|
value.add(amount, cost);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value = amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
130
xact.h
130
xact.h
|
|
@ -37,7 +37,15 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
// These flags persist with the object
|
class entry_t;
|
||||||
|
class account_t;
|
||||||
|
|
||||||
|
class xact_t;
|
||||||
|
typedef std::list<xact_t *> xacts_list;
|
||||||
|
|
||||||
|
class xact_t : public supports_flags<>, public scope_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
#define XACT_NORMAL 0x0000 // no flags at all, a basic transaction
|
#define XACT_NORMAL 0x0000 // no flags at all, a basic transaction
|
||||||
#define XACT_VIRTUAL 0x0001 // the account was specified with (parens)
|
#define XACT_VIRTUAL 0x0001 // the account was specified with (parens)
|
||||||
#define XACT_BALANCE 0x0002 // the account was specified with [brackets]
|
#define XACT_BALANCE 0x0002 // the account was specified with [brackets]
|
||||||
|
|
@ -47,37 +55,32 @@ namespace ledger {
|
||||||
#define XACT_GENERATED 0x0020 // transaction was not found in a journal
|
#define XACT_GENERATED 0x0020 // transaction was not found in a journal
|
||||||
#define XACT_TEMP 0x0040 // transaction is a temporary object
|
#define XACT_TEMP 0x0040 // transaction is a temporary object
|
||||||
|
|
||||||
class entry_t;
|
|
||||||
class account_t;
|
|
||||||
|
|
||||||
class xact_t : public supports_flags<>, public scope_t
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum state_t { UNCLEARED, CLEARED, PENDING };
|
enum state_t { UNCLEARED, CLEARED, PENDING };
|
||||||
|
|
||||||
entry_t * entry;
|
entry_t * entry;
|
||||||
state_t state;
|
|
||||||
account_t * account;
|
account_t * account;
|
||||||
|
state_t state;
|
||||||
|
|
||||||
optional<date_t> _date;
|
optional<date_t> _date;
|
||||||
optional<date_t> _date_eff;
|
optional<date_t> _date_eff;
|
||||||
|
optional<string> note;
|
||||||
|
|
||||||
amount_t amount;
|
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<string> note;
|
|
||||||
istream_pos_type beg_pos;
|
istream_pos_type beg_pos;
|
||||||
unsigned long beg_line;
|
unsigned long beg_line;
|
||||||
istream_pos_type end_pos;
|
istream_pos_type end_pos;
|
||||||
unsigned long end_line;
|
unsigned long end_line;
|
||||||
|
|
||||||
mutable void * data;
|
|
||||||
static bool use_effective_date;
|
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 = XACT_NORMAL)
|
||||||
: supports_flags<>(_flags), entry(NULL),
|
: supports_flags<>(_flags), entry(NULL), account(_account),
|
||||||
state(UNCLEARED), account(_account),
|
state(UNCLEARED), beg_pos(0), beg_line(0), end_pos(0), end_line(0)
|
||||||
beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL)
|
|
||||||
{
|
{
|
||||||
TRACE_CTOR(xact_t, "account_t *, flags_t");
|
TRACE_CTOR(xact_t, "account_t *, flags_t");
|
||||||
}
|
}
|
||||||
|
|
@ -85,9 +88,9 @@ class xact_t : public supports_flags<>, public scope_t
|
||||||
const amount_t& _amount,
|
const amount_t& _amount,
|
||||||
flags_t _flags = XACT_NORMAL,
|
flags_t _flags = XACT_NORMAL,
|
||||||
const optional<string>& _note = none)
|
const optional<string>& _note = none)
|
||||||
: supports_flags<>(_flags), entry(NULL), state(UNCLEARED),
|
: supports_flags<>(_flags), entry(NULL), account(_account),
|
||||||
account(_account), amount(_amount), note(_note),
|
state(UNCLEARED), note(_note), amount(_amount),
|
||||||
beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL)
|
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 string&");
|
"account_t *, const amount_t&, flags_t, const string&");
|
||||||
|
|
@ -96,18 +99,18 @@ class xact_t : public supports_flags<>, public scope_t
|
||||||
: supports_flags<>(xact),
|
: supports_flags<>(xact),
|
||||||
scope_t(),
|
scope_t(),
|
||||||
entry(xact.entry),
|
entry(xact.entry),
|
||||||
state(xact.state),
|
|
||||||
account(xact.account),
|
account(xact.account),
|
||||||
|
state(xact.state),
|
||||||
_date(xact._date),
|
_date(xact._date),
|
||||||
_date_eff(xact._date_eff),
|
_date_eff(xact._date_eff),
|
||||||
|
note(xact.note),
|
||||||
amount(xact.amount),
|
amount(xact.amount),
|
||||||
cost(xact.cost),
|
cost(xact.cost),
|
||||||
note(xact.note),
|
|
||||||
beg_pos(xact.beg_pos),
|
beg_pos(xact.beg_pos),
|
||||||
beg_line(xact.beg_line),
|
beg_line(xact.beg_line),
|
||||||
end_pos(xact.end_pos),
|
end_pos(xact.end_pos),
|
||||||
end_line(xact.end_line),
|
end_line(xact.end_line),
|
||||||
data(xact.data) // 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");
|
||||||
}
|
}
|
||||||
|
|
@ -129,6 +132,95 @@ class xact_t : public supports_flags<>, public scope_t
|
||||||
virtual expr_t::ptr_op_t lookup(const string& name);
|
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||||
|
|
||||||
bool valid() const;
|
bool valid() const;
|
||||||
|
|
||||||
|
struct xdata_t : public supports_flags<>
|
||||||
|
{
|
||||||
|
#define XACT_EXT_RECEIVED 0x01
|
||||||
|
#define XACT_EXT_HANDLED 0x02
|
||||||
|
#define XACT_EXT_TO_DISPLAY 0x04
|
||||||
|
#define XACT_EXT_DISPLAYED 0x08
|
||||||
|
#define XACT_EXT_NO_TOTAL 0x10
|
||||||
|
#define XACT_EXT_SORT_CALC 0x20
|
||||||
|
#define XACT_EXT_COMPOUND 0x40
|
||||||
|
#define XACT_EXT_MATCHES 0x80
|
||||||
|
|
||||||
|
value_t total;
|
||||||
|
value_t sort_value;
|
||||||
|
value_t value;
|
||||||
|
unsigned int index;
|
||||||
|
date_t date;
|
||||||
|
account_t * account;
|
||||||
|
void * ptr;
|
||||||
|
|
||||||
|
optional<xacts_list> component_xacts;
|
||||||
|
|
||||||
|
xdata_t() : supports_flags<>(), index(0), account(NULL), ptr(NULL) {
|
||||||
|
TRACE_CTOR(xdata_t, "");
|
||||||
|
}
|
||||||
|
~xdata_t() throw() {
|
||||||
|
TRACE_DTOR(xdata_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void remember_xact(xact_t& xact) {
|
||||||
|
if (! component_xacts)
|
||||||
|
component_xacts = xacts_list();
|
||||||
|
component_xacts->push_back(&xact);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_component_xacts() const {
|
||||||
|
return component_xacts && ! component_xacts->empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_component_xacts(xacts_list& xacts) {
|
||||||
|
foreach (xact_t * xact, xacts)
|
||||||
|
remember_xact(*xact);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void walk_component_xacts(item_handler<xact_t>& handler) const {
|
||||||
|
foreach (xact_t * xact, *component_xacts)
|
||||||
|
handler(*xact);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// This variable holds a pointer to "extended data" which is usually
|
||||||
|
// produced only during reporting, and only for the transaction set being
|
||||||
|
// reported. It's a memory-saving measure to delay allocation until the
|
||||||
|
// last possible moment.
|
||||||
|
mutable optional<xdata_t> xdata_;
|
||||||
|
|
||||||
|
bool has_xdata() const {
|
||||||
|
return xdata_;
|
||||||
|
}
|
||||||
|
void clear_xdata() {
|
||||||
|
xdata_ = none;
|
||||||
|
}
|
||||||
|
xdata_t& xdata() {
|
||||||
|
if (! xdata_)
|
||||||
|
xdata_ = xdata_t();
|
||||||
|
return *xdata_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_to_value(value_t& value);
|
||||||
|
|
||||||
|
date_t reported_date() const {
|
||||||
|
if (xdata_ && is_valid(xdata_->date))
|
||||||
|
return xdata_->date;
|
||||||
|
return
|
||||||
|
date();
|
||||||
|
}
|
||||||
|
|
||||||
|
account_t * reported_account() {
|
||||||
|
if (xdata_)
|
||||||
|
if (account_t * acct = xdata_->account)
|
||||||
|
return acct;
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
const account_t * reported_account() const {
|
||||||
|
return const_cast<xact_t *>(this)->reported_account();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
15
xml.cc
15
xml.cc
|
|
@ -381,9 +381,9 @@ void format_xml_entries::format_last_entry()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
foreach (const xact_t * xact, last_entry->xacts) {
|
foreach (xact_t * xact, last_entry->xacts) {
|
||||||
if (xact_has_xdata(*xact) &&
|
if (xact->has_xdata() &&
|
||||||
xact_xdata_(*xact).dflags & XACT_TO_DISPLAY) {
|
xact->xdata().has_flags(XACT_EXT_TO_DISPLAY)) {
|
||||||
if (first) {
|
if (first) {
|
||||||
output_stream << " <en:xacts>\n";
|
output_stream << " <en:xacts>\n";
|
||||||
first = false;
|
first = false;
|
||||||
|
|
@ -427,9 +427,8 @@ void format_xml_entries::format_last_entry()
|
||||||
}
|
}
|
||||||
|
|
||||||
output_stream << " <tr:amount>\n";
|
output_stream << " <tr:amount>\n";
|
||||||
if (xact_xdata_(*xact).dflags & XACT_COMPOUND)
|
if (xact->xdata().has_flags(XACT_EXT_COMPOUND))
|
||||||
xml_write_value(output_stream,
|
xml_write_value(output_stream, xact->xdata().value, 10);
|
||||||
xact_xdata_(*xact).value, 10);
|
|
||||||
else
|
else
|
||||||
xml_write_value(output_stream, value_t(xact->amount), 10);
|
xml_write_value(output_stream, value_t(xact->amount), 10);
|
||||||
output_stream << " </tr:amount>\n";
|
output_stream << " </tr:amount>\n";
|
||||||
|
|
@ -448,13 +447,13 @@ void format_xml_entries::format_last_entry()
|
||||||
|
|
||||||
if (show_totals) {
|
if (show_totals) {
|
||||||
output_stream << " <total>\n";
|
output_stream << " <total>\n";
|
||||||
xml_write_value(output_stream, xact_xdata_(*xact).total, 10);
|
xml_write_value(output_stream, xact->xdata().total, 10);
|
||||||
output_stream << " </total>\n";
|
output_stream << " </total>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
output_stream << " </xact>\n";
|
output_stream << " </xact>\n";
|
||||||
|
|
||||||
xact_xdata_(*xact).dflags |= XACT_DISPLAYED;
|
xact->xdata().add_flags(XACT_EXT_DISPLAYED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue