summaryrefslogtreecommitdiff
path: root/journal.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2005-06-22 23:04:38 +0000
committerJohn Wiegley <johnw@newartisans.com>2008-04-13 02:41:11 -0400
commit5175fdcd6c495b62ca5246843fa0228b03549de9 (patch)
treee79bac0d55176f1bb7293b3626c64639c8d8c84e /journal.cc
parent81e4851a6c7841046ed18c712d57153006f09c57 (diff)
downloadfork-ledger-5175fdcd6c495b62ca5246843fa0228b03549de9.tar.gz
fork-ledger-5175fdcd6c495b62ca5246843fa0228b03549de9.tar.bz2
fork-ledger-5175fdcd6c495b62ca5246843fa0228b03549de9.zip
(finalize): If a "basket" account is being used,
balance single transaction entries into it. Also, fixed two entry balancing issues. (finalize): If a "catch all" transaction (a transaction with no amount) is present in an entry, it will now balance all unbalanced quantities in the entry. Before its use was much more restricted. (journal_t::add_entry): Set the "journal" pointer before calling the finalize hooks, so that the finalizers have access to the proposed journal the entry wishes to be added to (if it fails, the pointer is cleared).
Diffstat (limited to 'journal.cc')
-rw-r--r--journal.cc76
1 files changed, 63 insertions, 13 deletions
diff --git a/journal.cc b/journal.cc
index 1af0342f..70dcf177 100644
--- a/journal.cc
+++ b/journal.cc
@@ -85,12 +85,20 @@ bool entry_base_t::finalize()
if (no_amounts)
return true;
+ if (journal && journal->basket && transactions.size() == 1) {
+ assert(balance.type < value_t::BALANCE);
+ transaction_t * nxact = new transaction_t(journal->basket);
+ // The amount doesn't need to be set because the code below will
+ // balance this transaction against the other.
+ add_transaction(nxact);
+ }
+
// If one transaction of a two-line transaction is of a different
// commodity than the others, and it has no per-unit price,
// determine its price by dividing the unit count into the value of
// the balance. This is done for the last eligible commodity.
- if (balance.type == value_t::BALANCE &&
+ if (balance && balance.type == value_t::BALANCE &&
((balance_t *) balance.data)->amounts.size() == 2)
for (transactions_list::const_iterator x = transactions.begin();
x != transactions.end();
@@ -127,20 +135,59 @@ bool entry_base_t::finalize()
! ((*x)->flags & TRANSACTION_BALANCE)))
continue;
- if (! empty_allowed || ! balance || balance.type != value_t::AMOUNT)
- return false;
-
+ if (! empty_allowed)
+ break;
empty_allowed = false;
- // If one transaction gives no value at all -- and all the
- // rest are of the same commodity -- then its value is the
- // inverse of the computed value of the others.
+ // If one transaction gives no value at all, its value will become
+ // the inverse of the value of the others. If multiple
+ // commodities are involved, multiple transactions will be
+ // generated to balance them all.
+
+ balance_t * bal = NULL;
+ switch (balance.type) {
+ case value_t::BALANCE_PAIR:
+ bal = &((balance_pair_t *) balance.data)->quantity;
+ // fall through...
+
+ case value_t::BALANCE:
+ if (! bal)
+ bal = (balance_t *) balance.data;
+
+ if (bal->amounts.size() < 2) {
+ balance.cast(value_t::AMOUNT);
+ } else {
+ bool first = true;
+ for (amounts_map::const_iterator i = bal->amounts.begin();
+ i != bal->amounts.end();
+ i++) {
+ amount_t amt = (*i).second;
+ amt.negate();
+
+ if (first) {
+ (*x)->amount = amt;
+ first = false;
+ } else {
+ transaction_t * nxact = new transaction_t((*x)->account);
+ add_transaction(nxact);
+ nxact->amount = amt;
+ }
+
+ balance += amt;
+ }
+ }
+ break;
+
+ case value_t::AMOUNT:
+ (*x)->amount = *((amount_t *) balance.data);
+ (*x)->amount.negate();
- assert(balance.type == value_t::AMOUNT);
- (*x)->amount = *((amount_t *) balance.data);
- (*x)->amount.negate();
+ balance += (*x)->amount;
+ break;
- balance = 0L;
+ default:
+ break;
+ }
}
return ! balance;
@@ -394,12 +441,15 @@ journal_t::~journal_t()
bool journal_t::add_entry(entry_t * entry)
{
+ entry->journal = this;
+
if (! entry->finalize() ||
- ! run_hooks(entry_finalize_hooks, *entry))
+ ! run_hooks(entry_finalize_hooks, *entry)) {
+ entry->journal = NULL;
return false;
+ }
entries.push_back(entry);
- entry->journal = this;
for (transactions_list::const_iterator i = entry->transactions.begin();
i != entry->transactions.end();