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 c916ef4ee3..ca83dcdcc3 100644 --- a/gnucash/import-export/csv-imp/gnc-imp-props-tx.hpp +++ b/gnucash/import-export/csv-imp/gnc-imp-props-tx.hpp @@ -197,12 +197,14 @@ struct GncPreSplit { public: GncPreSplit (int date_format, int currency_format) : m_date_format{date_format}, - m_currency_format{currency_format}{}; + 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; } + void set_pre_trans (std::shared_ptr pre_trans) { m_pre_trans = pre_trans; } + std::shared_ptr get_pre_trans (void) { return m_pre_trans; } StrVec verify_essentials (void); void create_split(std::shared_ptr draft_trans); @@ -211,6 +213,7 @@ public: ErrMap errors(); private: + std::shared_ptr m_pre_trans; int m_date_format; int m_currency_format; boost::optional m_action; diff --git a/gnucash/import-export/csv-imp/gnc-import-tx.cpp b/gnucash/import-export/csv-imp/gnc-import-tx.cpp index 4d4c2bad44..b0f19291c2 100644 --- a/gnucash/import-export/csv-imp/gnc-import-tx.cpp +++ b/gnucash/import-export/csv-imp/gnc-import-tx.cpp @@ -404,10 +404,13 @@ void GncTxImport::tokenize (bool guessColTypes) { auto length = tokenized_line.size(); if (length > 0) + { + auto pretrans = std::make_shared(date_format(), m_settings.m_multi_split); + auto presplit = std::make_shared(date_format(), currency_format()); + presplit->set_pre_trans (std::move (pretrans)); m_parsed_lines.push_back (std::make_tuple (tokenized_line, ErrMap(), - std::make_shared(date_format(), m_settings.m_multi_split), - std::make_shared(date_format(), currency_format()), - false)); + std::move (presplit), false)); + } if (length > max_cols) max_cols = length; } @@ -564,9 +567,9 @@ std::string GncTxImport::verify () std::shared_ptr GncTxImport::trans_properties_to_trans (std::vector::iterator& parsed_line) { auto created_trans = false; - std::shared_ptr trans_props; std::shared_ptr split_props; - std::tie(std::ignore, std::ignore, trans_props, split_props, std::ignore) = *parsed_line; + std::tie(std::ignore, std::ignore, split_props, std::ignore) = *parsed_line; + auto trans_props = split_props->get_pre_trans(); auto account = split_props->get_account(); QofBook* book = gnc_account_get_book (account); @@ -616,10 +619,10 @@ void GncTxImport::create_transaction (std::vector::iterator& parse { StrVec line; ErrMap errors; - std::shared_ptr trans_props = nullptr; std::shared_ptr split_props = nullptr; bool skip_line = false; - std::tie(line, errors, trans_props, split_props, skip_line) = *parsed_line; + std::tie(line, errors, split_props, skip_line) = *parsed_line; + auto trans_props = split_props->get_pre_trans(); if (skip_line) return; @@ -715,98 +718,88 @@ void GncTxImport::update_pre_trans_split_props (uint32_t row, uint32_t col, GncT * with a previous line and should no longer be after the transprop is changed. * This doesn't apply for the GncPreSplit so we just get a pointer to it for easier processing. */ - auto trans_props = std::make_shared (*(std::get(m_parsed_lines[row])).get()); auto split_props = std::get(m_parsed_lines[row]); + auto trans_props = std::make_shared (*(split_props->get_pre_trans()).get()); - try + /* Deal with trans properties first as this may change the trans->split relationships + * in case of multi-split imports */ + if ((old_type > GncTransPropType::NONE) && (old_type <= GncTransPropType::TRANS_PROPS)) + trans_props->reset (old_type); + if ((new_type > GncTransPropType::NONE) && (new_type <= GncTransPropType::TRANS_PROPS)) { - /* Start by resetting the value of the old_type (may throw!). */ - if ((old_type > GncTransPropType::NONE) && (old_type <= GncTransPropType::TRANS_PROPS)) - trans_props->reset (old_type); - if ((old_type > GncTransPropType::TRANS_PROPS) && (old_type <= GncTransPropType::SPLIT_PROPS)) - { - split_props->reset (old_type); - if (is_multi_col_prop(old_type)) - { + auto value = std::string(); - /* All amount columns may appear more than once. The net amount - * needs to be recalculated rather than just reset if one column - * is unset. */ - for (auto col_it = m_settings.m_column_types.cbegin(); - col_it < m_settings.m_column_types.cend(); - col_it++) - if (*col_it == old_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 (old_type, value); - } - } - } + if (col < std::get(m_parsed_lines[row]).size()) + value = std::get(m_parsed_lines[row]).at(col); - /* Next attempt to set the value for new_type (may throw!) */ - if ((new_type > GncTransPropType::NONE) && (new_type <= GncTransPropType::TRANS_PROPS)) - { - auto value = std::string(); - - if (col < std::get(m_parsed_lines[row]).size()) - value = std::get(m_parsed_lines[row]).at(col); - - trans_props->set(new_type, value); - } - - if ((new_type > GncTransPropType::TRANS_PROPS) && (new_type <= GncTransPropType::SPLIT_PROPS)) - { - /* All amount columns may appear more than once. The net amount - * needs to be recalculated rather than just reset if one column - * is set. */ - if (is_multi_col_prop(new_type)) - { - split_props->reset(new_type); - /* 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 == new_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 (new_type, value); - } - } - else - { - auto value = std::get(m_parsed_lines[row]).at(col); - split_props->set(new_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()); + trans_props->set(new_type, value); } - /* All value updates are finished by now, time to determine - * what to do with the updated GncPreTrans copy. - * - * For multi-split input data this line may be part of a transaction - * that has already been started by a previous line. In that case - * reuse the GncPreTrans from that previous line (which we track - * in m_parent). - * In all other cases our new GncPreTrans should be used for this line - * and be marked as the new potential m_parent for subsequent lines. - */ + + /* All transaction related value updates are finished now, + * time to determine what to do with the updated GncPreTrans copy. + * + * For multi-split input data this line may be part of a transaction + * that has already been started by a previous line. In that case + * reuse the GncPreTrans from that previous line (which we track + * in m_parent). + * In all other cases our new GncPreTrans should be used for this line + * and be marked as the new potential m_parent for subsequent lines. + */ if (m_settings.m_multi_split && trans_props->is_part_of(m_parent)) - std::get(m_parsed_lines[row]) = m_parent; + split_props->set_pre_trans (m_parent); else { - std::get(m_parsed_lines[row]) = trans_props; + split_props->set_pre_trans (trans_props); m_parent = trans_props; } + + /* Next handle any split related property changes */ + if ((old_type > GncTransPropType::TRANS_PROPS) && (old_type <= GncTransPropType::SPLIT_PROPS)) + { + split_props->reset (old_type); + if (is_multi_col_prop(old_type)) + { + + /* All amount columns may appear more than once. The net amount + * needs to be recalculated rather than just reset if one column + * is unset. */ + for (auto col_it = m_settings.m_column_types.cbegin(); + col_it < m_settings.m_column_types.cend(); + col_it++) + if (*col_it == old_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 (old_type, value); + } + } + } + if ((new_type > GncTransPropType::TRANS_PROPS) && (new_type <= GncTransPropType::SPLIT_PROPS)) + { + /* All amount columns may appear more than once. The net amount + * needs to be recalculated rather than just reset if one column + * is set. */ + if (is_multi_col_prop(new_type)) + { + split_props->reset(new_type); + /* 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 == new_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 (new_type, value); + } + } + else + { + auto value = std::get(m_parsed_lines[row]).at(col); + split_props->set(new_type, value); + } + } } @@ -841,10 +834,11 @@ GncTxImport::set_column_type (uint32_t position, GncTransPropType type, bool for /* Reset date and currency formats for each trans/split props object * to ensure column updates use the most recent one */ - std::get(*parsed_lines_it)->set_date_format (m_settings.m_date_format); - std::get(*parsed_lines_it)->set_multi_split (m_settings.m_multi_split); - std::get(*parsed_lines_it)->set_date_format (m_settings.m_date_format); - std::get(*parsed_lines_it)->set_currency_format (m_settings.m_currency_format); + auto split_props = std::get(*parsed_lines_it); + split_props->get_pre_trans()->set_date_format (m_settings.m_date_format); + split_props->get_pre_trans()->set_multi_split (m_settings.m_multi_split); + split_props->set_date_format (m_settings.m_date_format); + split_props->set_currency_format (m_settings.m_currency_format); uint32_t row = parsed_lines_it - m_parsed_lines.begin(); @@ -852,8 +846,8 @@ GncTxImport::set_column_type (uint32_t position, GncTransPropType type, bool for update_pre_trans_split_props (row, position, old_type, type); /* Report errors if there are any */ - auto all_errors = std::get(*parsed_lines_it)->errors(); - all_errors.merge (std::get(*parsed_lines_it)->errors()); + auto all_errors = split_props->get_pre_trans()->errors(); + all_errors.merge (split_props->errors()); std::get(*parsed_lines_it) = all_errors; } } diff --git a/gnucash/import-export/csv-imp/gnc-import-tx.hpp b/gnucash/import-export/csv-imp/gnc-import-tx.hpp index 4351a1d892..f2676a77f7 100644 --- a/gnucash/import-export/csv-imp/gnc-import-tx.hpp +++ b/gnucash/import-export/csv-imp/gnc-import-tx.hpp @@ -58,7 +58,6 @@ extern const gchar* currency_format_user[]; enum parse_line_cols { PL_INPUT, PL_ERROR, - PL_PRETRANS, PL_PRESPLIT, PL_SKIP }; @@ -70,7 +69,6 @@ using StrVec = std::vector; * with std::get to access the columns. */ using parse_line_t = std::tuple, std::shared_ptr, bool>;