summaryrefslogtreecommitdiff
path: root/src/xact.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2009-11-11 03:41:59 -0500
committerJohn Wiegley <johnw@newartisans.com>2009-11-11 04:22:37 -0500
commite8ea2d4938fcbb0988fd1e2021d97a519c67ffd8 (patch)
tree3aadd6947972d1b802f89b90db683994071b134c /src/xact.cc
parentafe87280e091d4f094f068c5f21aecccd2d1831b (diff)
downloadfork-ledger-e8ea2d4938fcbb0988fd1e2021d97a519c67ffd8.tar.gz
fork-ledger-e8ea2d4938fcbb0988fd1e2021d97a519c67ffd8.tar.bz2
fork-ledger-e8ea2d4938fcbb0988fd1e2021d97a519c67ffd8.zip
Automated postings defer amount expression calculation
This allows for value expressions to be used which reference the incoming posting, for example: = Income:Clients: (Liabilities:Taxes:VAT1) (floor(amount) * 1) (Liabilities:Taxes:VAT2) 0.19 2009/07/27 * Invoice Assets:Bank:Checking $1,190.45 Income:Clients:ACME_Inc The automated posting for VAT1 will use the floored amount multiplied by a factor, while the posting for VAT2 multiples the whole amount as before.
Diffstat (limited to 'src/xact.cc')
-rw-r--r--src/xact.cc47
1 files changed, 29 insertions, 18 deletions
diff --git a/src/xact.cc b/src/xact.cc
index d94464a6..8ac5280a 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -480,7 +480,7 @@ bool xact_t::valid() const
return true;
}
-void auto_xact_t::extend_xact(xact_base_t& xact, bool post_handler)
+void auto_xact_t::extend_xact(xact_base_t& xact)
{
posts_list initial_posts(xact.posts.begin(), xact.posts.end());
@@ -490,20 +490,32 @@ void auto_xact_t::extend_xact(xact_base_t& xact, bool post_handler)
if (! initial_post->has_flags(ITEM_GENERATED) &&
predicate(*initial_post)) {
foreach (post_t * post, posts) {
- amount_t amt;
- assert(post->amount);
- if (! post->amount.commodity()) {
- if ((post_handler &&
- ! initial_post->has_flags(POST_CALCULATED)) ||
- initial_post->amount.is_null())
- continue;
- amt = initial_post->amount * post->amount;
+ amount_t post_amount;
+ if (post->amount.is_null()) {
+ if (! post->amount_expr)
+ throw_(amount_error,
+ _("Automated transaction's posting has no amount"));
+
+ bind_scope_t bound_scope(*scope_t::default_scope, *initial_post);
+ value_t result(post->amount_expr->calc(bound_scope));
+ if (result.is_long()) {
+ post_amount = result.to_amount();
+ } else {
+ if (! result.is_amount())
+ throw_(amount_error,
+ _("Amount expressions must result in a simple amount"));
+ post_amount = result.as_amount();
+ }
} else {
- if (post_handler)
- continue;
- amt = post->amount;
+ post_amount = post->amount;
}
+ amount_t amt;
+ if (! post_amount.commodity())
+ amt = initial_post->amount * post_amount;
+ else
+ amt = post_amount;
+
IF_DEBUG("xact.extend") {
DEBUG("xact.extend",
"Initial post on line " << initial_post->pos->beg_line << ": "
@@ -517,12 +529,12 @@ void auto_xact_t::extend_xact(xact_base_t& xact, bool post_handler)
DEBUG("xact.extend",
"Posting on line " << post->pos->beg_line << ": "
- << "amount " << post->amount << ", amt " << amt
- << " (precision " << post->amount.precision()
+ << "amount " << post_amount << ", amt " << amt
+ << " (precision " << post_amount.precision()
<< " != " << amt.precision() << ")");
#if defined(DEBUG_ON)
- if (post->amount.keep_precision())
+ if (post_amount.keep_precision())
DEBUG("xact.extend", " precision is kept");
if (amt.keep_precision())
DEBUG("xact.extend", " amt precision is kept");
@@ -556,11 +568,10 @@ void auto_xact_t::extend_xact(xact_base_t& xact, bool post_handler)
}
void extend_xact_base(journal_t * journal,
- xact_base_t& base,
- bool post_handler)
+ xact_base_t& base)
{
foreach (auto_xact_t * xact, journal->auto_xacts)
- xact->extend_xact(base, post_handler);
+ xact->extend_xact(base);
}
void to_xml(std::ostream& out, const xact_t& xact)