Allow @ and @@ cost specifiers on the xact command

This commit is contained in:
John Wiegley 2009-10-31 02:54:50 -04:00
parent a88a4c55b2
commit 451b0e9b76

View file

@ -54,6 +54,8 @@ namespace {
bool from;
optional<mask_t> account_mask;
optional<amount_t> amount;
optional<string> cost_operator;
optional<amount_t> cost;
post_template_t() : from(false) {}
};
@ -111,6 +113,10 @@ namespace {
if (post.amount)
out << _(" Amount: ") << *post.amount << std::endl;
if (post.cost)
out << _(" Cost: ") << *post.cost_operator
<< " " << *post.cost << std::endl;
}
}
}
@ -148,6 +154,8 @@ namespace {
string arg = (*begin).to_string();
if (arg == "at") {
if (begin == end)
throw std::runtime_error(_("Invalid xact command arguments"));
tmpl.payee_mask = (*++begin).to_string();
}
else if (arg == "to" || arg == "from") {
@ -155,22 +163,41 @@ namespace {
tmpl.posts.push_back(xact_template_t::post_template_t());
post = &tmpl.posts.back();
}
if (begin == end)
throw std::runtime_error(_("Invalid xact command arguments"));
post->account_mask = mask_t((*++begin).to_string());
post->from = arg == "from";
}
else if (arg == "on") {
if (begin == end)
throw std::runtime_error(_("Invalid xact command arguments"));
tmpl.date = parse_date((*++begin).to_string());
check_for_date = false;
}
else if (arg == "code") {
if (begin == end)
throw std::runtime_error(_("Invalid xact command arguments"));
tmpl.code = (*++begin).to_string();
}
else if (arg == "note") {
if (begin == end)
throw std::runtime_error(_("Invalid xact command arguments"));
tmpl.note = (*++begin).to_string();
}
else if (arg == "rest") {
; // just ignore this argument
}
else if (arg == "@" || arg == "@@") {
amount_t cost;
post->cost_operator = arg;
if (begin == end)
throw std::runtime_error(_("Invalid xact command arguments"));
arg = (*++begin).to_string();
if (! cost.parse(arg, amount_t::PARSE_SOFT_FAIL |
amount_t::PARSE_NO_MIGRATE))
throw std::runtime_error(_("Invalid xact command arguments"));
post->cost = cost;
}
else {
// Without a preposition, it is either:
//
@ -443,6 +470,25 @@ namespace {
}
}
if (post.cost) {
if (post.cost->sign() < 0)
throw parse_error(_("A posting's cost may not be negative"));
post.cost->in_place_unround();
if (*post.cost_operator == "@") {
// For the sole case where the cost might be uncommoditized,
// guarantee that the commodity of the cost after multiplication
// is the same as it was before.
commodity_t& cost_commodity(post.cost->commodity());
*post.cost *= new_post->amount;
post.cost->set_commodity(cost_commodity);
}
new_post->cost = *post.cost;
DEBUG("derive.xact", "Copied over posting cost");
}
if (found_commodity &&
! new_post->amount.is_null() &&
! new_post->amount.has_commodity()) {