From a596727d3d2cef76e7347f3695d5d04067b24d19 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 22 May 2010 14:49:46 -0400 Subject: Interpolate uses of $account in automated postings Fixes 5CB52887-408E-48F0-8798-3C640D0295B3 --- src/xact.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/xact.cc') diff --git a/src/xact.cc b/src/xact.cc index 344f66ea..3c2505af 100644 --- a/src/xact.cc +++ b/src/xact.cc @@ -716,8 +716,14 @@ void auto_xact_t::extend_xact(xact_base_t& xact) account_t * account = post->account; string fullname = account->fullname(); assert(! fullname.empty()); - if (fullname == "$account" || fullname == "@account") - account = initial_post->account; + + if (contains(fullname, "$account")) { + fullname = regex_replace(fullname, regex("\\$account\\>"), + initial_post->account->fullname()); + while (account->parent) + account = account->parent; + account = account->find_account(fullname); + } // Copy over details so that the resulting post is a mirror of // the automated xact's one. -- cgit v1.2.3 From 9557a9d955f4272ac4ad7b727af18ab388b1f92e Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 22 May 2010 20:50:43 -0400 Subject: A minor fix to transaction auto-balancing It allows transactions like the following to auto-balance: 1999/08/16 Sell AAPL Assets:Broker $585 Expense:Broker:Commissions $15 Assets:Broker -10 AAPL {$30} @ $60 Income:Capital Gains --- src/xact.cc | 85 +++++++++++++++++++++++++++++-------------------------------- 1 file changed, 40 insertions(+), 45 deletions(-) (limited to 'src/xact.cc') diff --git a/src/xact.cc b/src/xact.cc index 3c2505af..f63835c9 100644 --- a/src/xact.cc +++ b/src/xact.cc @@ -172,44 +172,8 @@ bool xact_base_t::finalize() add_post(null_post); } - if (null_post != NULL) { - // If one post has no value at all, its value will become the inverse of - // the rest. If multiple commodities are involved, multiple posts are - // generated to balance them all. - - DEBUG("xact.finalize", "there was a null posting"); - - if (balance.is_balance()) { - bool first = true; - const balance_t& bal(balance.as_balance()); - foreach (const balance_t::amounts_map::value_type& pair, bal.amounts) { - if (first) { - null_post->amount = pair.second.negated(); - null_post->add_flags(POST_CALCULATED); - first = false; - } else { - post_t * p = new post_t(null_post->account, pair.second.negated(), - ITEM_GENERATED | POST_CALCULATED); - p->set_state(null_post->state()); - add_post(p); - } - } - } - else if (balance.is_amount()) { - null_post->amount = balance.as_amount().negated(); - null_post->add_flags(POST_CALCULATED); - } - else if (balance.is_long()) { - null_post->amount = amount_t(- balance.as_long()); - null_post->add_flags(POST_CALCULATED); - } - else if (! balance.is_null() && ! balance.is_realzero()) { - throw_(balance_error, _("Transaction does not balance")); - } - balance = NULL_VALUE; - } - else if (balance.is_balance() && - balance.as_balance().amounts.size() == 2) { + if (balance.is_balance() && + balance.as_balance().amounts.size() == 2) { // When an xact involves two different commodities (regardless of how // many posts there are) determine the conversion ratio by dividing the // total value of one commodity by the total value of the other. This @@ -293,12 +257,6 @@ bool xact_base_t::finalize() } } - // Now that the post list has its final form, calculate the balance once - // more in terms of total cost, accounting for any possible gain/loss - // amounts. - - DEBUG("xact.finalize", "resolved balance = " << balance); - posts_list copy(posts); foreach (post_t * post, copy) { @@ -340,7 +298,44 @@ bool xact_base_t::finalize() } } - DEBUG("xact.finalize", "final balance = " << balance); + if (null_post != NULL) { + // If one post has no value at all, its value will become the inverse of + // the rest. If multiple commodities are involved, multiple posts are + // generated to balance them all. + + DEBUG("xact.finalize", "there was a null posting"); + + if (balance.is_balance()) { + bool first = true; + const balance_t& bal(balance.as_balance()); + foreach (const balance_t::amounts_map::value_type& pair, bal.amounts) { + if (first) { + null_post->amount = pair.second.negated(); + null_post->add_flags(POST_CALCULATED); + first = false; + } else { + post_t * p = new post_t(null_post->account, pair.second.negated(), + ITEM_GENERATED | POST_CALCULATED); + p->set_state(null_post->state()); + add_post(p); + } + } + } + else if (balance.is_amount()) { + null_post->amount = balance.as_amount().negated(); + null_post->add_flags(POST_CALCULATED); + } + else if (balance.is_long()) { + null_post->amount = amount_t(- balance.as_long()); + null_post->add_flags(POST_CALCULATED); + } + else if (! balance.is_null() && ! balance.is_realzero()) { + throw_(balance_error, _("Transaction does not balance")); + } + balance = NULL_VALUE; + + } + DEBUG("xact.finalize", "resolved balance = " << balance); if (! balance.is_null() && ! balance.is_zero()) { add_error_context(item_context(*this, _("While balancing transaction"))); -- cgit v1.2.3 From 4f3b39e22c7a7743132ead79b1e092929679de44 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sun, 30 May 2010 02:55:02 -0600 Subject: Empty notes and tags now return null values --- src/filters.cc | 84 +++++++++++++++++++----------------- src/item.cc | 9 ++-- src/post.cc | 12 ++++-- src/xact.cc | 2 +- test/baseline/opt-code-as-payee.test | 4 +- 5 files changed, 60 insertions(+), 51 deletions(-) (limited to 'src/xact.cc') diff --git a/src/filters.cc b/src/filters.cc index 6915144d..6e4aeee3 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -69,14 +69,16 @@ void post_splitter::operator()(post_t& post) bind_scope_t bound_scope(report, post); value_t result(group_by_expr.calc(bound_scope)); - value_to_posts_map::iterator i = posts_map.find(result); - if (i != posts_map.end()) { - (*i).second.push_back(&post); - } else { - std::pair inserted - = posts_map.insert(value_to_posts_map::value_type(result, posts_list())); - assert(inserted.second); - (*inserted.first).second.push_back(&post); + if (! result.is_null()) { + value_to_posts_map::iterator i = posts_map.find(result); + if (i != posts_map.end()) { + (*i).second.push_back(&post); + } else { + std::pair inserted + = posts_map.insert(value_to_posts_map::value_type(result, posts_list())); + assert(inserted.second); + (*inserted.first).second.push_back(&post); + } } } @@ -837,41 +839,43 @@ void transfer_details::operator()(post_t& post) bind_scope_t bound_scope(scope, temp); value_t substitute(expr.calc(bound_scope)); - switch (which_element) { - case SET_DATE: - temp.xdata().date = substitute.to_date(); - break; - - case SET_ACCOUNT: { - string account_name = substitute.to_string(); - if (! account_name.empty() && - account_name[account_name.length() - 1] != ':') { - account_t * prev_account = temp.account; - temp.account->remove_post(&temp); - - account_name += ':'; - account_name += prev_account->fullname(); - - std::list account_names; - split_string(account_name, ':', account_names); - temp.account = create_temp_account_from_path(account_names, temps, - xact.journal->master); - temp.account->add_post(&temp); - - temp.account->add_flags(prev_account->flags()); - if (prev_account->has_xdata()) - temp.account->xdata().add_flags(prev_account->xdata().flags()); + if (! substitute.is_null()) { + switch (which_element) { + case SET_DATE: + temp.xdata().date = substitute.to_date(); + break; + + case SET_ACCOUNT: { + string account_name = substitute.to_string(); + if (! account_name.empty() && + account_name[account_name.length() - 1] != ':') { + account_t * prev_account = temp.account; + temp.account->remove_post(&temp); + + account_name += ':'; + account_name += prev_account->fullname(); + + std::list account_names; + split_string(account_name, ':', account_names); + temp.account = create_temp_account_from_path(account_names, temps, + xact.journal->master); + temp.account->add_post(&temp); + + temp.account->add_flags(prev_account->flags()); + if (prev_account->has_xdata()) + temp.account->xdata().add_flags(prev_account->xdata().flags()); + } + break; } - break; - } - case SET_PAYEE: - xact.payee = substitute.to_string(); - break; + case SET_PAYEE: + xact.payee = substitute.to_string(); + break; - default: - assert(false); - break; + default: + assert(false); + break; + } } item_handler::operator()(temp); diff --git a/src/item.cc b/src/item.cc index 14a0896f..0a22b260 100644 --- a/src/item.cc +++ b/src/item.cc @@ -227,7 +227,7 @@ namespace { return NULL_VALUE; } value_t get_note(item_t& item) { - return string_value(item.note ? *item.note : empty_string); + return item.note ? string_value(*item.note) : NULL_VALUE; } value_t has_tag(call_scope_t& args) { @@ -260,7 +260,8 @@ namespace { return false; } - value_t get_tag(call_scope_t& args) { + value_t get_tag(call_scope_t& args) + { item_t& item(find_scope(args)); optional str; @@ -292,14 +293,14 @@ namespace { if (str) return string_value(*str); else - return string_value(empty_string); + return NULL_VALUE; } value_t get_pathname(item_t& item) { if (item.pos) return string_value(item.pos->pathname.string()); else - return string_value(empty_string); + return NULL_VALUE; } value_t get_beg_pos(item_t& item) { diff --git a/src/post.cc b/src/post.cc index f1f3e96a..7dc15830 100644 --- a/src/post.cc +++ b/src/post.cc @@ -150,7 +150,7 @@ namespace { if (post.xact->code) return string_value(*post.xact->code); else - return string_value(empty_string); + return NULL_VALUE; } value_t get_payee(post_t& post) { @@ -158,9 +158,13 @@ namespace { } value_t get_note(post_t& post) { - string note = post.note ? *post.note : empty_string; - note += post.xact->note ? *post.xact->note : empty_string; - return string_value(note); + if (post.note || post.xact->note) { + string note = post.note ? *post.note : empty_string; + note += post.xact->note ? *post.xact->note : empty_string; + return string_value(note); + } else { + return NULL_VALUE; + } } value_t get_magnitude(post_t& post) { diff --git a/src/xact.cc b/src/xact.cc index f63835c9..569e5869 100644 --- a/src/xact.cc +++ b/src/xact.cc @@ -468,7 +468,7 @@ namespace { if (xact.code) return string_value(*xact.code); else - return string_value(empty_string); + return NULL_VALUE; } value_t get_payee(xact_t& xact) { diff --git a/test/baseline/opt-code-as-payee.test b/test/baseline/opt-code-as-payee.test index c2988626..99aa182e 100644 --- a/test/baseline/opt-code-as-payee.test +++ b/test/baseline/opt-code-as-payee.test @@ -28,7 +28,7 @@ reg --payee=code 08-Feb-01 102 Assets:Cash $-20.00 0 08-Feb-28 103 Expenses:Books $20.00 $20.00 08-Feb-28 103 Assets:Cash $-20.00 0 -08-Mar-01 Expenses:Books $30.00 $30.00 -08-Mar-01 Assets:Cash $-30.00 0 +08-Mar-01 March Expenses:Books $30.00 $30.00 +08-Mar-01 March Assets:Cash $-30.00 0 >>>2 === 0 -- cgit v1.2.3