From 451b0e9b767d67cb116549b6fb508ace83af7d60 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Sat, 31 Oct 2009 02:54:50 -0400 Subject: Allow @ and @@ cost specifiers on the xact command --- src/derive.cc | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'src/derive.cc') diff --git a/src/derive.cc b/src/derive.cc index ef2d1e51..df27d4b6 100644 --- a/src/derive.cc +++ b/src/derive.cc @@ -54,6 +54,8 @@ namespace { bool from; optional account_mask; optional amount; + optional cost_operator; + optional 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()) { -- cgit v1.2.3