diff options
-rw-r--r-- | src/commodity.cc | 7 | ||||
-rw-r--r-- | src/post.cc | 12 | ||||
-rw-r--r-- | src/report.cc | 8 | ||||
-rw-r--r-- | src/report.h | 5 | ||||
-rw-r--r-- | src/textual.cc | 2 | ||||
-rw-r--r-- | src/xact.cc | 20 |
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; } |