summaryrefslogtreecommitdiff
path: root/src/xact.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/xact.cc')
-rw-r--r--src/xact.cc123
1 files changed, 60 insertions, 63 deletions
diff --git a/src/xact.cc b/src/xact.cc
index 4fe3e6e6..35d61edd 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -124,27 +124,13 @@ bool xact_base_t::finalize()
amount_t& p(post->cost ? *post->cost : post->amount);
if (! p.is_null()) {
DEBUG("xact.finalize", "post must balance = " << p.reduced());
- if (! post->cost && post->amount.has_annotation() &&
- 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).unrounded();
- DEBUG("xact.finalize",
- "annotation price = " << *post->amount.annotation().price);
- DEBUG("xact.finalize", "amount = " << post->amount);
- DEBUG("xact.finalize", "priced cost = " << *post->cost);
- post->add_flags(POST_COST_CALCULATED);
- add_or_set_value(balance, post->cost->rounded().reduced());
- } else {
- // If the amount was a cost, it very likely has the "keep_precision"
- // flag set, meaning commodity display precision is ignored when
- // displaying the amount. We never want this set for the balance,
- // so we must clear the flag in a temporary to avoid it propagating
- // into the balance.
- add_or_set_value(balance, p.keep_precision() ?
- p.rounded().reduced() : p.reduced());
- }
+ // If the amount was a cost, it very likely has the
+ // "keep_precision" flag set, meaning commodity display precision
+ // is ignored when displaying the amount. We never want this set
+ // for the balance, so we must clear the flag in a temporary to
+ // avoid it propagating into the balance.
+ add_or_set_value(balance, p.keep_precision() ?
+ p.rounded().reduced() : p.reduced());
}
else if (null_post) {
throw_(std::logic_error,
@@ -173,14 +159,15 @@ bool xact_base_t::finalize()
add_post(null_post);
}
- if (balance.is_balance() &&
+ if (! null_post && 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
// establishes the per-unit cost for this post for both commodities.
- DEBUG("xact.finalize", "there were exactly two commodities");
+ DEBUG("xact.finalize",
+ "there were exactly two commodities, and no null post");
bool saw_cost = false;
post_t * top_post = NULL;
@@ -268,55 +255,65 @@ bool xact_base_t::finalize()
posts_list copy(posts);
- foreach (post_t * post, copy) {
- if (! post->cost)
- continue;
+ if (has_date()) {
+ foreach (post_t * post, copy) {
+ if (! post->cost)
+ continue;
- if (post->amount.commodity() == post->cost->commodity())
- throw_(balance_error,
- _("A posting's cost must be of a different commodity than its amount"));
+ if (post->amount.commodity() == post->cost->commodity())
+ throw_(balance_error,
+ _("A posting's cost must be of a different commodity than its amount"));
- cost_breakdown_t breakdown =
- commodity_pool_t::current_pool->exchange
+ cost_breakdown_t breakdown =
+ commodity_pool_t::current_pool->exchange
(post->amount, *post->cost, false,
datetime_t(date(), time_duration(0, 0, 0, 0)));
- if (post->amount.has_annotation() &&
- breakdown.basis_cost.commodity() == breakdown.final_cost.commodity()) {
- if (amount_t gain_loss = breakdown.basis_cost - breakdown.final_cost) {
- DEBUG("xact.finalize", "gain_loss = " << gain_loss);
- gain_loss.in_place_round();
- DEBUG("xact.finalize", "gain_loss rounds to = " << gain_loss);
-
- if (post->must_balance())
- add_or_set_value(balance, gain_loss.reduced());
-
- account_t * account;
- if (gain_loss.sign() > 0)
- account = journal->find_account(_("Equity:Capital Gains"));
- else
- account = journal->find_account(_("Equity:Capital Losses"));
-
- post_t * p = new post_t(account, gain_loss, ITEM_GENERATED);
- p->set_state(post->state());
- if (post->has_flags(POST_VIRTUAL)) {
- DEBUG("xact.finalize", "gain_loss came from a virtual post");
- p->add_flags(post->flags() & (POST_VIRTUAL | POST_MUST_BALANCE));
+ if (post->amount.has_annotation() && post->amount.annotation().price) {
+ if (breakdown.basis_cost.commodity() == breakdown.final_cost.commodity()) {
+ if (amount_t gain_loss = breakdown.basis_cost - breakdown.final_cost) {
+ DEBUG("xact.finalize", "gain_loss = " << gain_loss);
+ gain_loss.in_place_round();
+ DEBUG("xact.finalize", "gain_loss rounds to = " << gain_loss);
+
+ if (post->must_balance())
+ add_or_set_value(balance, gain_loss.reduced());
+
+ account_t * account;
+ if (gain_loss.sign() > 0)
+ account = journal->find_account(_("Equity:Capital Gains"));
+ else
+ account = journal->find_account(_("Equity:Capital Losses"));
+
+ post_t * p = new post_t(account, gain_loss, ITEM_GENERATED);
+ p->set_state(post->state());
+ if (post->has_flags(POST_VIRTUAL)) {
+ DEBUG("xact.finalize", "gain_loss came from a virtual post");
+ p->add_flags(post->flags() & (POST_VIRTUAL | POST_MUST_BALANCE));
+ }
+ add_post(p);
+ DEBUG("xact.finalize", "added gain_loss, balance = " << balance);
+ } else {
+ DEBUG("xact.finalize", "gain_loss would have displayed as zero");
+ }
}
- add_post(p);
- DEBUG("xact.finalize", "added gain_loss, balance = " << balance);
} else {
- DEBUG("xact.finalize", "gain_loss would have display as zero");
+ if (post->amount.has_annotation()) {
+ if (breakdown.amount.has_annotation())
+ breakdown.amount.annotation().tag = post->amount.annotation().tag;
+ else
+ breakdown.amount.annotate
+ (annotation_t(none, none, post->amount.annotation().tag));
+ }
+ post->amount = breakdown.amount;
+ DEBUG("xact.finalize", "added breakdown, balance = " << balance);
}
- } else {
- post->amount = breakdown.amount;
- DEBUG("xact.finalize", "added breakdown, balance = " << balance);
- }
- if (post->has_flags(POST_COST_FIXATED) &&
- post->amount.has_annotation() && post->amount.annotation().price) {
- DEBUG("xact.finalize", "fixating annotation price");
- post->amount.annotation().add_flags(ANNOTATION_PRICE_FIXATED);
+ if (post->has_flags(POST_COST_FIXATED) &&
+ post->amount.has_annotation() && post->amount.annotation().price) {
+ DEBUG("xact.finalize", "fixating annotation price");
+ post->amount.annotation().add_flags(ANNOTATION_PRICE_FIXATED);
+ }
}
}