Transactional assignments (i.e., confirmed balances) are working now.
This commit is contained in:
parent
0135c28049
commit
7d1809cb15
4 changed files with 66 additions and 50 deletions
39
src/entry.cc
39
src/entry.cc
|
|
@ -130,7 +130,7 @@ bool entry_base_t::finalize()
|
||||||
// :generatedp t))
|
// :generatedp t))
|
||||||
// (add-xact entry null-xact)))
|
// (add-xact entry null-xact)))
|
||||||
|
|
||||||
if (journal && journal->basket && xacts.size() == 1) {
|
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, XACT_GENERATED);
|
||||||
|
|
@ -173,10 +173,14 @@ bool entry_base_t::finalize()
|
||||||
XACT_GENERATED));
|
XACT_GENERATED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else if (balance.is_amount()) {
|
||||||
null_xact->amount = balance.as_amount().negate();
|
null_xact->amount = balance.as_amount().negate();
|
||||||
null_xact->add_flags(XACT_CALCULATED);
|
null_xact->add_flags(XACT_CALCULATED);
|
||||||
}
|
}
|
||||||
|
else if (! balance.is_null() && ! balance.is_realzero()) {
|
||||||
|
throw_(balance_error, "Entry does not balance");
|
||||||
|
}
|
||||||
balance = NULL_VALUE;
|
balance = NULL_VALUE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -300,28 +304,37 @@ bool entry_base_t::finalize()
|
||||||
// (format-value balance :width 20)))
|
// (format-value balance :width 20)))
|
||||||
|
|
||||||
if (! balance.is_null()) {
|
if (! balance.is_null()) {
|
||||||
balance.round();
|
balance.in_place_round();
|
||||||
if (! balance.is_zero()) {
|
if (! balance.is_zero()) {
|
||||||
#if 0
|
#if 0
|
||||||
error * err =
|
new entry_context(*this, "While balancing entry:");
|
||||||
new balance_error("Entry does not balance",
|
|
||||||
new entry_context(*this, "While balancing entry:"));
|
|
||||||
err->context.push_front
|
|
||||||
(new value_context(balance, "Unbalanced remainder is:"));
|
|
||||||
throw err;
|
|
||||||
#endif
|
#endif
|
||||||
|
add_error_context("Unbalanced remainder is: ");
|
||||||
|
add_error_context(value_context(balance));
|
||||||
|
throw_(balance_error, "Entry does not balance");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the final calculated totals each to their related account
|
// Add the final calculated totals each to their related account
|
||||||
|
|
||||||
if (dynamic_cast<entry_t *>(this)) {
|
if (dynamic_cast<entry_t *>(this)) {
|
||||||
|
bool all_null = true;
|
||||||
foreach (xact_t * xact, xacts) {
|
foreach (xact_t * xact, xacts) {
|
||||||
// jww (2008-08-09): For now, this feature only works for
|
if (! xact->amount.is_null()) {
|
||||||
// non-specific commodities.
|
all_null = false;
|
||||||
add_or_set_value(xact->account->xdata().value,
|
|
||||||
xact->amount.strip_annotations());
|
// jww (2008-08-09): For now, this feature only works for
|
||||||
|
// non-specific commodities.
|
||||||
|
add_or_set_value(xact->account->xdata().value, xact->amount);
|
||||||
|
|
||||||
|
DEBUG("entry.finalize.totals",
|
||||||
|
"Total for " << xact->account->fullname() << " + "
|
||||||
|
<< xact->amount.strip_annotations() << ": "
|
||||||
|
<< xact->account->xdata().value.strip_annotations());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (all_null)
|
||||||
|
return false; // ignore this entry completely
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -313,71 +313,78 @@ xact_t * parse_xact(char * line, account_t * account, entry_t * entry = NULL)
|
||||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||||
"Found a balance assignment indicator");
|
"Found a balance assignment indicator");
|
||||||
if (in.good() && ! in.eof()) {
|
if (in.good() && ! in.eof()) {
|
||||||
amount_t amt;
|
xact->assigned_amount = amount_t();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
istream_pos_type beg = in.tellg();
|
istream_pos_type beg = in.tellg();
|
||||||
|
|
||||||
optional<expr_t> total_expr =
|
xact->assigned_amount_expr =
|
||||||
parse_amount_expr(in, amt, xact.get(), EXPR_PARSE_NO_MIGRATE);
|
parse_amount_expr(in, *xact->assigned_amount, xact.get(),
|
||||||
|
EXPR_PARSE_NO_MIGRATE);
|
||||||
|
|
||||||
if (amt.is_null())
|
if (xact->assigned_amount->is_null())
|
||||||
throw parse_error
|
throw parse_error
|
||||||
("An assigned balance must evaluate to a constant value");
|
("An assigned balance must evaluate to a constant value");
|
||||||
|
|
||||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||||
"XACT assign: parsed amt = " << amt);
|
"XACT assign: parsed amt = " << *xact->assigned_amount);
|
||||||
|
|
||||||
if (total_expr) {
|
if (xact->assigned_amount_expr) {
|
||||||
istream_pos_type end = in.tellg();
|
istream_pos_type end = in.tellg();
|
||||||
total_expr->set_text(string("=") +
|
xact->assigned_amount_expr->set_text
|
||||||
string(line, long(beg), long(end - beg)));
|
(string("=") + string(line, long(beg), long(end - beg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// jww (2008-08-02): Save total_expr somewhere!
|
|
||||||
|
|
||||||
account_t::xdata_t& xdata(xact->account->xdata());
|
account_t::xdata_t& xdata(xact->account->xdata());
|
||||||
|
amount_t& amt(*xact->assigned_amount);
|
||||||
|
|
||||||
DEBUG("ledger.xact.assign", "account balance = " << xdata.value);
|
DEBUG("xact.assign",
|
||||||
DEBUG("ledger.xact.assign", "xact amount = " << amt);
|
"account balance = " << xdata.value.strip_annotations());
|
||||||
|
DEBUG("xact.assign",
|
||||||
|
"xact amount = " << amt.strip_annotations());
|
||||||
|
|
||||||
amount_t diff;
|
amount_t diff;
|
||||||
if (xdata.value.is_amount()) {
|
if (xdata.value.is_amount()) {
|
||||||
diff = amt - xdata.value.as_amount();
|
diff = amt - xdata.value.as_amount();
|
||||||
}
|
}
|
||||||
else if (xdata.value.is_balance()) {
|
else if (xdata.value.is_balance()) {
|
||||||
optional<amount_t> comm_bal =
|
if (optional<amount_t> comm_bal =
|
||||||
xdata.value.as_balance().commodity_amount(amt.commodity());
|
xdata.value.as_balance().commodity_amount(amt.commodity()))
|
||||||
diff = amt - (comm_bal ? *comm_bal : amount_t(0L));
|
diff = amt - *comm_bal;
|
||||||
|
else
|
||||||
|
diff = amt;
|
||||||
}
|
}
|
||||||
else if (xdata.value.is_balance_pair()) {
|
else if (xdata.value.is_balance_pair()) {
|
||||||
optional<amount_t> comm_bal =
|
if (optional<amount_t> comm_bal =
|
||||||
xdata.value.as_balance_pair().commodity_amount(amt.commodity());
|
xdata.value.as_balance_pair().commodity_amount(amt.commodity()))
|
||||||
diff = amt - (comm_bal ? *comm_bal : amount_t(0L));
|
diff = amt - *comm_bal;
|
||||||
|
else
|
||||||
|
diff = amt;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
diff = amt;
|
diff = amt;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG("ledger.xact.assign", "diff = " << diff);
|
DEBUG("xact.assign", "diff = " << diff.strip_annotations());
|
||||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||||
"XACT assign: diff = " << diff);
|
"XACT assign: diff = " << diff.strip_annotations());
|
||||||
|
|
||||||
if (! diff.is_realzero()) {
|
if (! diff.is_zero()) {
|
||||||
if (! xact->amount.is_null()) {
|
if (! xact->amount.is_null()) {
|
||||||
xact_t * temp =
|
diff -= xact->amount;
|
||||||
new xact_t(xact->account, diff,
|
if (! diff.is_zero()) {
|
||||||
XACT_GENERATED | XACT_CALCULATED);
|
xact_t * temp = new xact_t(xact->account, diff,
|
||||||
entry->add_xact(temp);
|
XACT_GENERATED | XACT_CALCULATED);
|
||||||
|
entry->add_xact(temp);
|
||||||
|
|
||||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||||
"Created balancing transaction");
|
"Created balancing transaction");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
xact->amount = diff;
|
xact->amount = diff;
|
||||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||||
"Overwrite null transaction");
|
"Overwrite null transaction");
|
||||||
}
|
}
|
||||||
xdata.value = amt;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const std::exception& err) {
|
catch (const std::exception& err) {
|
||||||
|
|
|
||||||
10
src/value.cc
10
src/value.cc
|
|
@ -1263,11 +1263,8 @@ bool value_t::is_realzero() const
|
||||||
return as_any_pointer().empty();
|
return as_any_pointer().empty();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(false);
|
throw_(value_error, "Cannot determine if " << label() << " is really zero");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
assert(false);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool value_t::is_zero() const
|
bool value_t::is_zero() const
|
||||||
|
|
@ -1296,11 +1293,8 @@ bool value_t::is_zero() const
|
||||||
return as_any_pointer().empty();
|
return as_any_pointer().empty();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(false);
|
throw_(value_error, "Cannot determine if " << label() << " is zero");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
assert(false);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t value_t::value(const optional<datetime_t>& moment) const
|
value_t value_t::value(const optional<datetime_t>& moment) const
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,8 @@ public:
|
||||||
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<expr_t> assigned_amount_expr;
|
||||||
|
|
||||||
istream_pos_type beg_pos;
|
istream_pos_type beg_pos;
|
||||||
unsigned long beg_line;
|
unsigned long beg_line;
|
||||||
|
|
@ -84,7 +86,7 @@ public:
|
||||||
{
|
{
|
||||||
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 = XACT_NORMAL,
|
||||||
const optional<string>& _note = none)
|
const optional<string>& _note = none)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue