From 28e5db429c3698d5d6add82d2037e5f99fa20e45 Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Sat, 28 Mar 2020 20:02:25 +0100 Subject: [PATCH] Bug 797133 - CSV Import of multicurrency transaction export in multiline form The csv parser was using xaccParseAmount to convert price strings into GncNumerics. However our export code can generate prices in rational form which xaccParseAmount can't convert. So for prices the csv parser now uses the expression parser instead to convert the string into a GncNumeric. --- .../csv-imp/gnc-imp-props-tx.cpp | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp index e196d1a7d6..ee5cc3bd10 100644 --- a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp +++ b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp @@ -35,6 +35,7 @@ extern "C" { #include "Account.h" #include "Transaction.h" #include "gnc-pricedb.h" +#include } @@ -193,6 +194,32 @@ gnc_commodity* parse_commodity (const std::string& comm_str) return comm; } + +static GncNumeric parse_price (const std::string &str) +{ + /* An empty field is treated as zero */ + if (str.empty()) + return GncNumeric{}; + + /* Strings otherwise containing not digits will be considered invalid */ + if(!boost::regex_search(str, boost::regex("[0-9]"))) + throw std::invalid_argument (_("Value doesn't appear to contain a valid number.")); + + auto expr = boost::make_u32regex("[[:Sc:]]"); + std::string str_no_symbols = boost::u32regex_replace(str, expr, ""); + + /* Convert based on user chosen currency format */ + gnc_numeric val = gnc_numeric_zero(); + char *endptr; + + auto success = gnc_exp_parser_parse (str.c_str(), &val, &endptr); + gnc_exp_parser_shutdown(); + if (!success) + throw std::invalid_argument (_("Price can't be parsed into a number.")); + + return GncNumeric(val); +} + void GncPreTrans::set (GncTransPropType prop_type, const std::string& value) { try @@ -437,7 +464,7 @@ void GncPreSplit::set (GncTransPropType prop_type, const std::string& value) case GncTransPropType::PRICE: m_price = boost::none; - m_price = parse_amount (value, m_currency_format); // Will throw if parsing fails + m_price = parse_price (value); // Will throw if parsing fails break; case GncTransPropType::REC_STATE: