From 5175fdcd6c495b62ca5246843fa0228b03549de9 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 22 Jun 2005 23:04:38 +0000 Subject: (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). --- journal.cc | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file 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(); -- cgit v1.2.3