summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/commodity.cc7
-rw-r--r--src/post.cc12
-rw-r--r--src/report.cc8
-rw-r--r--src/report.h5
-rw-r--r--src/textual.cc2
-rw-r--r--src/xact.cc20
6 files changed, 39 insertions, 15 deletions
diff --git a/src/commodity.cc b/src/commodity.cc
index 6b39d711..18bafc8e 100644
--- a/src/commodity.cc
+++ b/src/commodity.cc
@@ -413,20 +413,21 @@ commodity_t::exchange(const amount_t& amount,
if (commodity.annotated)
current_annotation = &as_annotated_commodity(commodity).details;
- amount_t per_unit_cost(is_per_unit ? cost : (cost / amount).unrounded());
+ amount_t per_unit_cost = (is_per_unit ? cost : cost / amount).abs();
DEBUG("commodity.prices.add", "exchange: per-unit-cost = " << per_unit_cost);
exchange(commodity, per_unit_cost, moment ? *moment : CURRENT_TIME());
cost_breakdown_t breakdown;
- breakdown.final_cost = ! is_per_unit ? cost : (cost * amount).unrounded();
+ breakdown.final_cost = ! is_per_unit ? cost : cost * amount;
DEBUG("commodity.prices.add",
"exchange: final-cost = " << breakdown.final_cost);
if (current_annotation && current_annotation->price)
- breakdown.basis_cost = (*current_annotation->price * amount).unrounded();
+ breakdown.basis_cost
+ = (*current_annotation->price * amount).unrounded();
else
breakdown.basis_cost = breakdown.final_cost;
diff --git a/src/post.cc b/src/post.cc
index 5c0d98e7..d99d1e97 100644
--- a/src/post.cc
+++ b/src/post.cc
@@ -319,9 +319,15 @@ bool post_t::valid() const
return false;
}
- if (cost && ! cost->valid()) {
- DEBUG("ledger.validate", "post_t: cost && ! cost->valid()");
- return false;
+ if (cost) {
+ if (! cost->valid()) {
+ DEBUG("ledger.validate", "post_t: cost && ! cost->valid()");
+ return false;
+ }
+ if (! cost->keep_precision()) {
+ DEBUG("ledger.validate", "post_t: ! cost->keep_precision()");
+ return false;
+ }
}
return true;
diff --git a/src/report.cc b/src/report.cc
index 8d673c78..a969a2b8 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -203,6 +203,12 @@ value_t report_t::fn_quantity(call_scope_t& scope)
return args.get<amount_t>(0).number();
}
+value_t report_t::fn_abs(call_scope_t& scope)
+{
+ interactive_t args(scope, "v");
+ return args.value_at(0).abs();
+}
+
value_t report_t::fn_truncated(call_scope_t& scope)
{
interactive_t args(scope, "v&ll");
@@ -568,6 +574,8 @@ expr_t::ptr_op_t report_t::lookup(const string& name)
return MAKE_FUNCTOR(report_t::fn_amount_expr);
else if (is_eq(p, "ansify_if"))
return MAKE_FUNCTOR(report_t::fn_ansify_if);
+ else if (is_eq(p, "abs"))
+ return MAKE_FUNCTOR(report_t::fn_abs);
break;
case 'c':
diff --git a/src/report.h b/src/report.h
index 82c605df..f92cb236 100644
--- a/src/report.h
+++ b/src/report.h
@@ -140,6 +140,7 @@ public:
value_t fn_quantity(call_scope_t& scope);
value_t fn_rounded(call_scope_t& scope);
value_t fn_truncated(call_scope_t& scope);
+ value_t fn_abs(call_scope_t& scope);
value_t fn_justify(call_scope_t& scope);
value_t fn_quoted(call_scope_t& scope);
value_t fn_join(call_scope_t& scope);
@@ -514,12 +515,12 @@ public:
" %(xact.uncleared ? (cleared ? \"* \" : (pending ? \"! \" : \"\")) : \"\")"
"%-34(account)"
" %12(calculated ? \"\" : justify(scrub(amount), 12, -1, true))"
- "%(has_cost & !priced ? \" @ \" + justify(scrub(cost / amount), 0) : \"\")"
+ "%(has_cost & !priced ? \" @ \" + justify(scrub(abs(cost / amount)), 0) : \"\")"
"%(comment | \"\")\n%/"
" %(xact.uncleared ? (cleared ? \"* \" : (pending ? \"! \" : \"\")) : \"\")"
"%-34(account)"
" %12(calculated ? \"\" : justify(scrub(amount), 12, -1, true))"
- "%(has_cost & !priced ? \" @ \" + justify(scrub(cost / amount), 0) : \"\")"
+ "%(has_cost & !priced ? \" @ \" + justify(scrub(abs(cost / amount)), 0) : \"\")"
"%(comment | \"\")\n%/\n");
});
diff --git a/src/textual.cc b/src/textual.cc
index a804fb1c..b3294d99 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -954,6 +954,8 @@ post_t * instance_t::parse_post(char * line,
if (post->cost->sign() < 0)
throw parse_error(_("A posting's cost may not be negative"));
+ post->cost->in_place_unround();
+
if (per_unit)
*post->cost *= post->amount;
diff --git a/src/xact.cc b/src/xact.cc
index 52ac68a6..e9d22da1 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -78,15 +78,16 @@ bool xact_base_t::finalize()
foreach (post_t * post, posts) {
if (! post->must_balance())
continue;
-
+
amount_t& p(post->cost ? *post->cost : post->amount);
- DEBUG("xact.finalize", "post must balance = " << p.reduced());
if (! p.is_null()) {
+ DEBUG("xact.finalize", "post must balance = " << p.reduced());
if (! post->cost && post->amount.is_annotated() &&
post->amount.annotation().price) {
// If the amount has no cost, but is annotated with a per-unit
// price, use the price times the amount as the cost
- post->cost = *post->amount.annotation().price * post->amount;
+ post->cost = (*post->amount.annotation().price *
+ post->amount).unrounded();
DEBUG("xact.finalize",
"annotation price = " << *post->amount.annotation().price);
DEBUG("xact.finalize", "amount = " << post->amount);
@@ -145,10 +146,11 @@ bool xact_base_t::finalize()
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);
+ ITEM_GENERATED | POST_CALCULATED);
p->set_state(null_post->state());
add_post(p);
}
@@ -228,7 +230,7 @@ bool xact_base_t::finalize()
DEBUG("xact.finalize", "total_cost = " << total_cost);
}
}
- per_unit_cost = (*y / *x).abs();
+ per_unit_cost = (*y / *x).abs().unrounded();
DEBUG("xact.finalize", "per_unit_cost = " << per_unit_cost);
@@ -254,7 +256,9 @@ bool xact_base_t::finalize()
DEBUG("xact.finalize", "resolved balance = " << balance);
- foreach (post_t * post, posts) {
+ posts_list copy(posts);
+
+ foreach (post_t * post, copy) {
if (! post->cost)
continue;
@@ -281,7 +285,7 @@ bool xact_base_t::finalize()
else
account = journal->find_account(_("Equity:Capital Losses"));
- post_t * p = new post_t(account, gain_loss.rounded(), ITEM_GENERATED);
+ post_t * p = new post_t(account, gain_loss, ITEM_GENERATED);
p->set_state(post->state());
add_post(p);
DEBUG("xact.finalize", "added gain_loss, balance = " << balance);
@@ -328,6 +332,8 @@ bool xact_base_t::finalize()
_("There cannot be null amounts after balancing a transaction"));
}
+ VERIFY(valid());
+
return true;
}