Fixed bugs relating to sign and rounding of costs
This commit is contained in:
parent
501949a364
commit
f1795e628b
6 changed files with 39 additions and 15 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
12
src/post.cc
12
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;
|
||||
|
|
|
|||
|
|
@ -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':
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
20
src/xact.cc
20
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue