diff options
author | John Wiegley <johnw@newartisans.com> | 2005-06-22 23:04:38 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2008-04-13 02:41:11 -0400 |
commit | 5175fdcd6c495b62ca5246843fa0228b03549de9 (patch) | |
tree | e79bac0d55176f1bb7293b3626c64639c8d8c84e /journal.cc | |
parent | 81e4851a6c7841046ed18c712d57153006f09c57 (diff) | |
download | fork-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.cc | 76 |
1 files changed, 63 insertions, 13 deletions
@@ -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(); |