From 25cc3307228d7ec6f216767f628bf241ae720d1d Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Wed, 28 Aug 2019 20:55:29 +0200 Subject: [PATCH] 797171 - Allow multiple credit/debit columns to be selected This required some tweaks in the core csv import code - first don't unset other deposit/withdrawal columns when selecting a second one - amounts have to be summed for all deposit/withdrawal colums I have added a new member function 'add' in addition to 'set' and 'reset' That function will only work for deposit or withdrawal columns --- .../csv-imp/gnc-imp-props-tx.cpp | 49 +++++++++++++++++++ .../csv-imp/gnc-imp-props-tx.hpp | 1 + .../import-export/csv-imp/gnc-import-tx.cpp | 44 ++++++++++++----- 3 files changed, 82 insertions(+), 12 deletions(-) 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 c1e3586953..e196d1a7d6 100644 --- a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp +++ b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp @@ -502,6 +502,55 @@ void GncPreSplit::reset (GncTransPropType prop_type) } } +void GncPreSplit::add (GncTransPropType prop_type, const std::string& value) +{ + try + { + // Drop any existing error for the prop_type we're about to add to + m_errors.erase(prop_type); + + Account *acct = nullptr; + auto num_val = GncNumeric(); + switch (prop_type) + { + case GncTransPropType::DEPOSIT: + num_val = parse_amount (value, m_currency_format); // Will throw if parsing fails + if (m_deposit) + num_val += *m_deposit; + m_deposit = num_val; + break; + + case GncTransPropType::WITHDRAWAL: + num_val = parse_amount (value, m_currency_format); // Will throw if parsing fails + if (m_withdrawal) + num_val += *m_withdrawal; + m_withdrawal = num_val; + break; + + default: + /* Issue a warning for all other prop_types. */ + PWARN ("%d can't be used to add values in a split", static_cast(prop_type)); + break; + } + } + catch (const std::invalid_argument& e) + { + auto err_str = std::string(_(gnc_csv_col_type_strs[prop_type])) + + std::string(_(" could not be understood.\n")) + + e.what(); + m_errors.emplace(prop_type, err_str); + throw std::invalid_argument (err_str); + } + catch (const std::out_of_range& e) + { + auto err_str = std::string(_(gnc_csv_col_type_strs[prop_type])) + + std::string(_(" could not be understood.\n")) + + e.what(); + m_errors.emplace(prop_type, err_str); + throw std::invalid_argument (err_str); + } +} + std::string GncPreSplit::verify_essentials (void) { auto err_msg = std::string(); diff --git a/gnucash/import-export/csv-imp/gnc-imp-props-tx.hpp b/gnucash/import-export/csv-imp/gnc-imp-props-tx.hpp index ee0052926a..b8936961fb 100644 --- a/gnucash/import-export/csv-imp/gnc-imp-props-tx.hpp +++ b/gnucash/import-export/csv-imp/gnc-imp-props-tx.hpp @@ -157,6 +157,7 @@ public: m_currency_format{currency_format}{}; void set (GncTransPropType prop_type, const std::string& value); void reset (GncTransPropType prop_type); + void add (GncTransPropType prop_type, const std::string& value); void set_date_format (int date_format) { m_date_format = date_format ;} void set_currency_format (int currency_format) { m_currency_format = currency_format; } std::string verify_essentials (void); diff --git a/gnucash/import-export/csv-imp/gnc-import-tx.cpp b/gnucash/import-export/csv-imp/gnc-import-tx.cpp index 99536136b9..df76f014b1 100644 --- a/gnucash/import-export/csv-imp/gnc-import-tx.cpp +++ b/gnucash/import-export/csv-imp/gnc-import-tx.cpp @@ -792,24 +792,41 @@ void GncTxImport::update_pre_split_props (uint32_t row, uint32_t col, GncTransPr auto split_props = std::get(m_parsed_lines[row]); - if (col == std::get(m_parsed_lines[row]).size()) - split_props->reset (prop_type); - else + split_props->reset (prop_type); + try { - try + // Except for Deposit or Withdrawal lines there can only be + // one column with a given property type. + if ((prop_type != GncTransPropType::DEPOSIT) && + (prop_type != GncTransPropType::WITHDRAWAL)) { auto value = std::get(m_parsed_lines[row]).at(col); split_props->set(prop_type, value); } - catch (const std::exception& e) + else { - /* Do nothing, just prevent the exception from escalating up - * However log the error if it happens on a row that's not skipped - */ - if (!std::get(m_parsed_lines[row])) - PINFO("User warning: %s", e.what()); + // For Deposits and Withdrawal we have to sum all columns with this property + for (auto col_it = m_settings.m_column_types.cbegin(); + col_it < m_settings.m_column_types.cend(); + col_it++) + { + if (*col_it == prop_type) + { + auto col_num = col_it - m_settings.m_column_types.cbegin(); + auto value = std::get(m_parsed_lines[row]).at(col_num); + split_props->add (prop_type, value); + } + } } } + catch (const std::exception& e) + { + /* Do nothing, just prevent the exception from escalating up + * However log the error if it happens on a row that's not skipped + */ + if (!std::get(m_parsed_lines[row])) + PINFO("User warning: %s", e.what()); + } } @@ -823,8 +840,11 @@ GncTxImport::set_column_type (uint32_t position, GncTransPropType type, bool for if ((type == old_type) && !force) return; /* Nothing to do */ - // Column types should be unique, so remove any previous occurrence of the new type - std::replace(m_settings.m_column_types.begin(), m_settings.m_column_types.end(), + // Column types except deposit and withdrawal should be unique, + // so remove any previous occurrence of the new type + if ((type != GncTransPropType::DEPOSIT) && + (type != GncTransPropType::WITHDRAWAL)) + std::replace(m_settings.m_column_types.begin(), m_settings.m_column_types.end(), type, GncTransPropType::NONE); m_settings.m_column_types.at (position) = type;