Cleanup commit

- improve comments
- improve variable and function names (to be more concise and to the point
- use 'Transfer Account' instead of 'Other Account' as that's the term used in the rest of gnucash
This commit is contained in:
Geert Janssens 2016-12-11 17:10:53 +01:00 committed by Geert Janssens
parent 90e5e96f8f
commit 854ee31989
5 changed files with 175 additions and 166 deletions

View File

@ -284,7 +284,7 @@ csv_import_trans_load_settings (CsvImportTrans *info)
if (info->settings_data->column_widths, NULL)
fwtok->cols_from_string (std::string(info->settings_data->column_widths));
info->parse_data->parse (false);
info->parse_data->tokenize (false);
gnc_csv_preview_update_assist (info);
}
}
@ -323,7 +323,7 @@ csv_import_trans_load_settings (CsvImportTrans *info)
int saved_col_type = atoi (columns[i]);
if (saved_col_type >= static_cast<int>(GncTransPropType::NONE) &&
saved_col_type <= static_cast<int>(GncTransPropType::OMEMO))
saved_col_type <= static_cast<int>(GncTransPropType::TMEMO))
{
col_type = static_cast<GncTransPropType>(saved_col_type);
info->parse_data->column_types.at(i) = col_type;
@ -693,7 +693,7 @@ csv_import_trans_file_chooser_confirm_cb (GtkWidget *button, CsvImportTrans *inf
{
parse_data->file_format (GncImpFileFormat::CSV);
parse_data->load_file (info->file_name);
parse_data->parse (true);
parse_data->tokenize (true);
}
catch (std::ifstream::failure& e)
{
@ -939,7 +939,7 @@ void sep_button_clicked (GtkWidget* widget, CsvImportTrans* info)
* configurations intact. */
try
{
info->parse_data->parse (false);
info->parse_data->tokenize (false);
}
catch (std::range_error &e)
{
@ -999,7 +999,7 @@ static void separated_or_fixed_selected (GtkToggleButton* csv_button, CsvImportT
info->parse_data->file_format (GncImpFileFormat::FIXED_WIDTH);
/* Reparse the data. */
info->parse_data->parse (false);
info->parse_data->tokenize (false);
/* Show the new data. */
gnc_csv_preview_update_assist (info);
@ -1050,7 +1050,7 @@ static void encoding_selected (GOCharmapSel* selector, const char* encoding,
try
{
info->parse_data->convert_encoding (encoding);
info->parse_data->parse (false);
info->parse_data->tokenize (false);
}
catch (...)
{
@ -1209,7 +1209,7 @@ fixed_context_menu_handler (GnumericPopupMenuElement const *element,
try
{
info->parse_data->parse (false);
info->parse_data->tokenize (false);
}
catch(std::range_error& e)
{
@ -1394,7 +1394,7 @@ split_column (CsvImportTrans* info, int col, int dx)
fwtok->col_split (col, rel_pos);
try
{
info->parse_data->parse (false);
info->parse_data->tokenize (false);
}
catch (std::range_error& e)
{
@ -1520,11 +1520,11 @@ bool preview_settings_valid (CsvImportTrans* info)
weight = weight + 1;
break;
case GncTransPropType::OACCOUNT:
case GncTransPropType::TACCOUNT:
oweight = oweight + 100;
break;
case GncTransPropType::OMEMO:
case GncTransPropType::TMEMO:
oweight = oweight + 1;
break;
default:
@ -1634,7 +1634,7 @@ bool get_list_of_accounts (CsvImportTrans* info, GtkTreeModel *store)
gtk_tree_model_get (ctstore, &iter1, 2 * i + 1, &col_type, -1);
/* We're only interested in columns of type ACCOUNT and OACCOUNT. */
if ((col_type == GncTransPropType::ACCOUNT) || (col_type == GncTransPropType::OACCOUNT))
if ((col_type == GncTransPropType::ACCOUNT) || (col_type == GncTransPropType::TACCOUNT))
{
/* Get an iterator for the row in the data store. */
if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(datastore), &iter2, NULL, j))
@ -1723,8 +1723,8 @@ static void gnc_csv_preview_update_assist (CsvImportTrans* info)
g_free (bodytypes);
/* Fill the data liststore with data from the file. */
info->num_of_rows = info->parse_data->orig_lines.size();
for (auto parse_line : info->parse_data->orig_lines)
info->num_of_rows = info->parse_data->parsed_lines.size();
for (auto parse_line : info->parse_data->parsed_lines)
{
// When previewing errors skip all lines that don't have errors
if (info->previewing_errors && std::get<1>(parse_line).empty())
@ -2462,8 +2462,8 @@ csv_import_trans_assistant_match_page_prepare (GtkAssistant *assistant,
/* Copy all of the transactions to the importer GUI. */
for (auto trans_it : info->parse_data->transactions)
{
auto trans_line = trans_it.second;
gnc_gen_trans_list_add_trans (info->gnc_csv_importer_gui, trans_line->trans);
auto draft_trans = trans_it.second;
gnc_gen_trans_list_add_trans (info->gnc_csv_importer_gui, draft_trans->trans);
}
}
}
@ -2563,7 +2563,7 @@ csv_import_trans_forward_page_func (gint current_page, gpointer user_data)
// Check to see if we have an account / other account columns
if (info->parse_data->check_for_column_type (GncTransPropType::ACCOUNT) ||
info->parse_data->check_for_column_type (GncTransPropType::OACCOUNT))
info->parse_data->check_for_column_type (GncTransPropType::TACCOUNT))
next_page = 4;
else
next_page = 5;
@ -2593,7 +2593,7 @@ csv_import_trans_forward_page_func (gint current_page, gpointer user_data)
{
/* Create transactions from the parsed data, first time with false
Subsequent times with true */
info->parse_data->parse_to_trans (info->account, info->match_parse_run);
info->parse_data->create_transactions (info->account, info->match_parse_run);
/* if there are errors, we jump back to preview to correct */
if (info->parse_data->parse_errors && !info->skip_errors)

View File

@ -55,8 +55,8 @@ std::map<GncTransPropType, const char*> gnc_csv_col_type_strs = {
{ GncTransPropType::WITHDRAWAL, N_("Withdrawal") },
{ GncTransPropType::BALANCE, N_("Balance") },
{ GncTransPropType::MEMO, N_("Memo") },
{ GncTransPropType::OACCOUNT, N_("Other Account") },
{ GncTransPropType::OMEMO, N_("Other Memo") }
{ GncTransPropType::TACCOUNT, N_("Transfer Account") },
{ GncTransPropType::TMEMO, N_("Transfer Memo") }
};
/* Regular expressions used to parse dates per date format */
@ -171,7 +171,7 @@ time64 parse_date (const std::string &date_str, int format)
* @param currency_format The currency format to use.
* @return a gnc_numeric on success, boost::none on failure
*/
static boost::optional<gnc_numeric> convert_amount_col_str (const std::string &str, int currency_format)
static boost::optional<gnc_numeric> parse_amount (const std::string &str, int currency_format)
{
/* If a cell is empty or just spaces return invalid amount */
if(!boost::regex_search(str, boost::regex("[0-9]")))
@ -206,24 +206,24 @@ static boost::optional<gnc_numeric> convert_amount_col_str (const std::string &s
}
void GncPreTrans::set_property (GncTransPropType prop_type, const std::string& prop_value_str, int date_format)
void GncPreTrans::set_property (GncTransPropType prop_type, const std::string& value, int date_format)
{
switch (prop_type)
{
case GncTransPropType::DATE:
m_date = parse_date (prop_value_str.c_str(), date_format); // Throws if parsing fails
m_date = parse_date (value.c_str(), date_format); // Throws if parsing fails
break;
case GncTransPropType::DESCRIPTION:
if (!prop_value_str.empty())
m_desc = prop_value_str;
if (!value.empty())
m_desc = value;
else
m_desc = boost::none;
break;
case GncTransPropType::NOTES:
if (!prop_value_str.empty())
m_notes = prop_value_str;
if (!value.empty())
m_notes = value;
else
m_notes = boost::none;
break;
@ -267,56 +267,56 @@ Transaction* GncPreTrans::create_trans (QofBook* book, gnc_commodity* currency)
}
void GncPreSplit::set_property (GncTransPropType prop_type, const std::string& prop_value_str, int currency_format)
void GncPreSplit::set_property (GncTransPropType prop_type, const std::string& value, int currency_format)
{
Account *acct = nullptr;
switch (prop_type)
{
case GncTransPropType::ACCOUNT:
acct = gnc_csv_account_map_search (prop_value_str.c_str());
acct = gnc_csv_account_map_search (value.c_str());
if (acct)
m_account = acct;
else
throw std::invalid_argument ("String can't be mapped back to an account.");
break;
case GncTransPropType::OACCOUNT:
acct = gnc_csv_account_map_search (prop_value_str.c_str());
case GncTransPropType::TACCOUNT:
acct = gnc_csv_account_map_search (value.c_str());
if (acct)
m_oaccount = acct;
m_taccount = acct;
else
throw std::invalid_argument ("String can't be mapped back to an account.");
break;
case GncTransPropType::MEMO:
if (!prop_value_str.empty())
m_memo = prop_value_str;
if (!value.empty())
m_memo = value;
else
m_memo = boost::none;
break;
case GncTransPropType::OMEMO:
if (!prop_value_str.empty())
m_omemo = prop_value_str;
case GncTransPropType::TMEMO:
if (!value.empty())
m_tmemo = value;
else
m_omemo = boost::none;
m_tmemo = boost::none;
break;
case GncTransPropType::NUM:
if (!prop_value_str.empty())
m_num = prop_value_str;
if (!value.empty())
m_num = value;
else
m_num = boost::none;
break;
case GncTransPropType::BALANCE:
m_balance = convert_amount_col_str (prop_value_str, currency_format); // Will throw if parsing fails
m_balance = parse_amount (value, currency_format); // Will throw if parsing fails
break;
case GncTransPropType::DEPOSIT:
m_deposit = convert_amount_col_str (prop_value_str, currency_format); // Will throw if parsing fails
m_deposit = parse_amount (value, currency_format); // Will throw if parsing fails
break;
case GncTransPropType::WITHDRAWAL:
m_withdrawal = convert_amount_col_str (prop_value_str, currency_format); // Will throw if parsing fails
m_withdrawal = parse_amount (value, currency_format); // Will throw if parsing fails
break;
default:
@ -366,9 +366,9 @@ boost::optional<gnc_numeric> GncPreSplit::create_split (Transaction* trans)
auto book = xaccTransGetBook (trans);
std::string num;
std::string memo;
std::string omemo;
std::string tmemo;
Account *account = nullptr;
Account *oaccount = nullptr;
Account *taccount = nullptr;
bool amount_set = false;
gnc_numeric deposit = { 0, 1 };
gnc_numeric withdrawal = { 0, 1 };
@ -376,12 +376,12 @@ boost::optional<gnc_numeric> GncPreSplit::create_split (Transaction* trans)
if (m_account)
account = *m_account;
if (m_oaccount)
oaccount = *m_oaccount;
if (m_taccount)
taccount = *m_taccount;
if (m_memo)
memo = *m_memo;
if (m_omemo)
omemo = *m_omemo;
if (m_tmemo)
tmemo = *m_tmemo;
if (m_num)
num = *m_num;
if (m_deposit)
@ -402,12 +402,12 @@ boost::optional<gnc_numeric> GncPreSplit::create_split (Transaction* trans)
/* Add a split with the cumulative amount value. */
trans_add_split (trans, account, book, amount, num, memo);
if (oaccount)
if (taccount)
/* Note: the current importer assumes at most 2 splits. This means the second split amount
* will be the negative of the the first split amount. We also only set the num field once,
* for the first split.
*/
trans_add_split (trans, oaccount, book, gnc_numeric_neg(amount), "", omemo);
trans_add_split (trans, taccount, book, gnc_numeric_neg(amount), "", tmemo);
created = true;

View File

@ -57,9 +57,9 @@ enum class GncTransPropType {
WITHDRAWAL,
BALANCE,
MEMO,
OACCOUNT,
OMEMO,
SPLIT_PROPS = OMEMO
TACCOUNT,
TMEMO,
SPLIT_PROPS = TMEMO
};
/** Maps all column types to a string representation.
@ -73,7 +73,7 @@ time64 parse_date (const std::string &date_str, int format);
struct GncPreTrans
{
public:
void set_property (GncTransPropType prop_type, const std::string& prop_value_str, int date_format = 0);
void set_property (GncTransPropType prop_type, const std::string& value, int date_format = 0);
std::string verify_essentials (void);
Transaction *create_trans (QofBook* book, gnc_commodity* currency);
@ -87,7 +87,7 @@ private:
struct GncPreSplit
{
public:
void set_property (GncTransPropType prop_type, const std::string& prop_value_str, int currency_format = 0);
void set_property (GncTransPropType prop_type, const std::string& value, int currency_format = 0);
std::string verify_essentials (void);
boost::optional<gnc_numeric> create_split(Transaction* trans);
@ -100,8 +100,8 @@ private:
boost::optional<gnc_numeric> m_withdrawal;
boost::optional<gnc_numeric> m_balance;
boost::optional<std::string> m_memo;
boost::optional<Account*> m_oaccount;
boost::optional<std::string> m_omemo;
boost::optional<Account*> m_taccount;
boost::optional<std::string> m_tmemo;
// Strictly speaking num is a transaction property
// However due to the option to swap num and action fields

View File

@ -57,6 +57,7 @@ G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
// };
//
/** Constructor for GncTxImport.
* @return Pointer to a new GncCSvParseData
*/
@ -87,7 +88,7 @@ GncTxImport::~GncTxImport()
* previously set file format was different and a
* filename was already set.
* @param format the new format to set
* @exception the reloading of the file may throw std::ifstream::failure
* @exception std::ifstream::failure if file reloading fails
*/
void GncTxImport::file_format(GncImpFileFormat format)
{
@ -112,6 +113,7 @@ void GncTxImport::file_format(GncImpFileFormat format)
tokenizer->encoding(new_encoding);
load_file(new_imp_file);
}
GncImpFileFormat GncTxImport::file_format()
{
return file_fmt;
@ -120,7 +122,6 @@ GncImpFileFormat GncTxImport::file_format()
/** Converts raw file data using a new encoding. This function must be
* called after load_file only if load_file guessed
* the wrong encoding.
* @param parse_data Data that is being parsed
* @param encoding Encoding that data should be translated using
*/
void GncTxImport::convert_encoding (const std::string& encoding)
@ -131,13 +132,8 @@ void GncTxImport::convert_encoding (const std::string& encoding)
}
/** Loads a file into a GncTxImport. This is the first function
* that must be called after creating a new GncTxImport. If this
* fails because the file couldn't be opened, no more functions can be
* called on the parse data until this succeeds (or until it fails
* because of an encoding guess error). If it fails because the
* encoding could not be guessed, gnc_csv_convert_encoding must be
* called until it succeeds.
* @param parse_data Data that is being parsed
* that must be called after creating a new GncTxImport. As long as
* this function didn't run successfully, the importer can't proceed.
* @param filename Name of the file that should be opened
* @exception may throw std::ifstream::failure on any io error
*/
@ -158,24 +154,25 @@ void GncTxImport::load_file (const std::string& filename)
}
}
/** Parses a file into cells. This requires having an encoding that
* works (see gnc_csv_convert_encoding). options should be
* set according to how the user wants before calling this
* function. (Note: this function must be called with guessColTypes as
* TRUE before it is ever called with it as FALSE.) (Note: if
* guessColTypes is TRUE, all the column types will be GncTransPropType::NONE
* right now.)
* @param guessColTypes TRUE to guess what the types of columns are based on the cell contents
* @exception throws std::range_error if parsing failed
/** Splits a file into cells. This requires having an encoding that
* works (see GncTxImport::convert_encoding). Tokenizing related options
* should be set to the user's selections before calling this
* function.
* Notes: - this function must be called with guessColTypes set to true once
* before calling it with guessColTypes set to false.
* - if guessColTypes is TRUE, all the column types will be set
* GncTransPropType::NONE right now as real guessing isn't implemented yet
* @param guessColTypes true to guess what the types of columns are based on the cell contents
* @exception std::range_error if tokenizing failed
*/
void GncTxImport::parse (bool guessColTypes)
void GncTxImport::tokenize (bool guessColTypes)
{
uint max_cols = 0;
tokenizer->tokenize();
orig_lines.clear();
parsed_lines.clear();
for (auto tokenized_line : tokenizer->get_tokens())
{
orig_lines.push_back (std::make_tuple (tokenized_line, std::string(),
parsed_lines.push_back (std::make_tuple (tokenized_line, std::string(),
std::make_shared<GncPreTrans>(), std::make_shared<GncPreSplit>()));
auto length = tokenized_line.size();
if (length > max_cols)
@ -183,9 +180,9 @@ void GncTxImport::parse (bool guessColTypes)
}
/* If it failed, generate an error. */
if (orig_lines.size() == 0)
if (parsed_lines.size() == 0)
{
throw (std::range_error ("Parsing failed."));
throw (std::range_error ("Tokenizing failed."));
return;
}
@ -211,16 +208,16 @@ void GncTxImport::parse (bool guessColTypes)
* - at least one of "Balance", "Deposit", or "Withdrawal"
* - "Account"
* Note account isn't checked for here as this has been done before
* @param parse_line The line we are checking
* @param parsed_line The line we are checking
* @exception std::invalid_argument in an essential property is missing
*/
static void trans_properties_verify_essentials (parse_line_t& orig_line)
static void trans_properties_verify_essentials (parse_line_t& parsed_line)
{
std::string error_message;
std::shared_ptr<GncPreTrans> trans_props;
std::shared_ptr<GncPreSplit> split_props;
std::tie(std::ignore, error_message, trans_props, split_props) = orig_line;
std::tie(std::ignore, error_message, trans_props, split_props) = parsed_line;
auto trans_error = trans_props->verify_essentials();
auto split_error = split_props->verify_essentials();
@ -238,19 +235,19 @@ static void trans_properties_verify_essentials (parse_line_t& orig_line)
if (!error_message.empty())
throw std::invalid_argument(error_message);
}
/** Create a Transaction from a map of transaction properties.
* Note: this function assumes all properties in the map have been verified
* to be valid. No further checks are performed here other than that
* the required properties are in the map
* @param orig_line The current line being parsed
* @return On success, a GncCsvTransLine; on failure, the trans pointer is NULL
/** Create a transaction and splits from a pair of trans and split property objects.
* Note: this function assumes all properties have been verified
* to be valid and the required properties are available.
* @param parsed_line The current line being parsed
* @return On success, a DraftTransaction; on failure a nullptr
*/
static GncCsvTransLine* trans_properties_to_trans (parse_line_t& orig_line)
static DraftTransaction* trans_properties_to_trans (parse_line_t& parsed_line)
{
std::string error_message;
std::shared_ptr<GncPreTrans> trans_props;
std::shared_ptr<GncPreSplit> split_props;
std::tie(std::ignore, error_message, trans_props, split_props) = orig_line;
std::tie(std::ignore, error_message, trans_props, split_props) = parsed_line;
auto account = split_props->get_account();
QofBook* book = gnc_account_get_book (account);
@ -261,30 +258,29 @@ static GncCsvTransLine* trans_properties_to_trans (parse_line_t& orig_line)
if (!trans)
return nullptr;
GncCsvTransLine* trans_line = g_new (GncCsvTransLine, 1);
trans_line->balance_set = false;
trans_line->balance = gnc_numeric_zero();
DraftTransaction* draft_trans = g_new (DraftTransaction, 1);
draft_trans->balance_set = false;
draft_trans->balance = gnc_numeric_zero();
auto balance = split_props->create_split(trans);
if (balance)
{
trans_line->balance_set = true;
trans_line->balance = *balance;
draft_trans->balance_set = true;
draft_trans->balance = *balance;
}
return trans_line;
return draft_trans;
}
void GncTxImport::adjust_balances (Account *account)
void GncTxImport::adjust_balances (void)
{
Split *split, *osplit;
Split *split, *tsplit;
/* balance_offset is how much the balance currently in the account
* differs from what it will be after the transactions are
* imported. This will be sum of all the previous transactions for
* any given transaction. */
auto balance_offset = double_to_gnc_numeric (0.0, xaccAccountGetCommoditySCU (account),
GNC_HOW_RND_ROUND_HALF_UP);
auto balance_offset = gnc_numeric_zero();
for (auto trans_iter : transactions)
{
auto trans_line = trans_iter.second;
@ -293,25 +289,25 @@ void GncTxImport::adjust_balances (Account *account)
time64 date = xaccTransGetDate (trans_line->trans);
/* Find what the balance should be by adding the offset to the actual balance. */
gnc_numeric existing_balance = gnc_numeric_add (balance_offset,
xaccAccountGetBalanceAsOfDate (account, date),
xaccAccountGetCommoditySCU (account),
xaccAccountGetBalanceAsOfDate (base_account, date),
xaccAccountGetCommoditySCU (base_account),
GNC_HOW_RND_ROUND_HALF_UP);
/* The amount of the transaction is the difference between the new and existing balance. */
gnc_numeric amount = gnc_numeric_sub (trans_line->balance,
existing_balance,
xaccAccountGetCommoditySCU (account),
xaccAccountGetCommoditySCU (base_account),
GNC_HOW_RND_ROUND_HALF_UP);
// Find home account split
split = xaccTransFindSplitByAccount (trans_line->trans, account);
split = xaccTransFindSplitByAccount (trans_line->trans, base_account);
xaccSplitSetAmount (split, amount);
xaccSplitSetValue (split, amount);
// If we have two splits, change other side
if (xaccTransCountSplits (trans_line->trans) == 2)
{
osplit = xaccSplitGetOtherSplit (split);
tsplit = xaccSplitGetOtherSplit (split);
xaccSplitSetAmount (split, amount);
xaccSplitSetValue (split, gnc_numeric_neg (amount));
}
@ -319,23 +315,23 @@ void GncTxImport::adjust_balances (Account *account)
/* This new transaction needs to be added to the balance offset. */
balance_offset = gnc_numeric_add (balance_offset,
amount,
xaccAccountGetCommoditySCU (account),
xaccAccountGetCommoditySCU (base_account),
GNC_HOW_RND_ROUND_HALF_UP);
}
}
}
void GncTxImport::parse_line_to_trans (parse_line_t& orig_line)
void GncTxImport::create_transaction (parse_line_t& parsed_line)
{
StrVec line;
std::string error_message;
std::shared_ptr<GncPreTrans> trans_props;
std::shared_ptr<GncPreSplit> split_props;
std::tie(line, error_message, trans_props, split_props) = orig_line;
std::tie(line, error_message, trans_props, split_props) = parsed_line;
error_message.clear();
/* Convert this import line into a map of transaction/split properties. */
/* Convert all tokens in this line into transaction/split properties. */
auto col_types_it = column_types.cbegin();
auto line_it = line.cbegin();
for (col_types_it, line_it;
@ -368,8 +364,8 @@ void GncTxImport::parse_line_to_trans (parse_line_t& orig_line)
auto line_acct = split_props->get_account();
if (!line_acct)
{
if (home_account)
split_props->set_account(home_account);
if (base_account)
split_props->set_account(base_account);
else
{
// Oops - the user didn't select an Account column *and* we didn't get a default value either!
@ -384,17 +380,17 @@ void GncTxImport::parse_line_to_trans (parse_line_t& orig_line)
/* If column parsing was successful, convert trans properties into a trans line. */
try
{
trans_properties_verify_essentials (orig_line);
trans_properties_verify_essentials (parsed_line);
/* If all went well, add this transaction to the list. */
/* We want to keep the transactions sorted by date in case we have
* to calculate the transaction's amount based on the user provided balances.
* The multimap should deal with this for us. */
auto trans_line = trans_properties_to_trans (orig_line);
if (trans_line)
auto draft_trans = trans_properties_to_trans (parsed_line);
if (draft_trans)
{
auto trans_date = xaccTransGetDate (trans_line->trans);
transactions.insert (std::pair<time64, GncCsvTransLine*>(trans_date,trans_line));
auto trans_date = xaccTransGetDate (draft_trans->trans);
transactions.insert (std::pair<time64, DraftTransaction*>(trans_date,draft_trans));
}
}
catch (const std::invalid_argument& e)
@ -406,23 +402,22 @@ void GncTxImport::parse_line_to_trans (parse_line_t& orig_line)
/** Creates a list of transactions from parsed data. Transactions that
* could be created from rows are placed in transactions;
* rows that fail are placed in error_lines. (Note: there
* is no way for this function to "fail," i.e. it only returns 0, so
* it may be changed to a void function in the future.)
* @param parse_data Data that is being parsed
* could be created from rows are placed in transactions; Lines that couldn't
* be converted are marked with the failure reason. These can be redone in
* a subsequent run with redo_errors set to true.
* @param account Account with which transactions are created
* @param redo_errors TRUE to convert only error data, FALSE for all data
* @return 0 on success, 1 on failure
* @param redo_errors true to convert only error data, false to convert all data
*/
int GncTxImport::parse_to_trans (Account* account,
bool redo_errors)
void GncTxImport::create_transactions (Account* account,
bool redo_errors)
{
/* Free error_lines and transactions if they
* already exist. */
if (!redo_errors) /* If we're redoing errors, we save freeing until the end. */
/* If a full conversion is requested (as opposed to only
* attempting to convers the lines which had errors in the previous run)
* clear all errors and possibly already created transactions. */
if (!redo_errors)
{
for (auto orig_line : orig_lines)
/* Clear error messages on full run */
for (auto orig_line : parsed_lines)
std::get<1>(orig_line).clear();
/* FIXME handle memory leak here!
@ -433,23 +428,25 @@ int GncTxImport::parse_to_trans (Account* account,
}
/* compute start and end iterators based on user-set restrictions */
auto orig_lines_it = orig_lines.begin();
std::advance(orig_lines_it, start_row);
auto parsed_lines_it = parsed_lines.begin();
std::advance(parsed_lines_it, start_row);
auto orig_lines_max = orig_lines.begin();
if (end_row > orig_lines.size())
orig_lines_max = orig_lines.end();
auto parsed_lines_max = parsed_lines.begin();
if (end_row > parsed_lines.size())
parsed_lines_max = parsed_lines.end();
else
std::advance(orig_lines_max, end_row);
std::advance(parsed_lines_max, end_row);
home_account = account;
base_account = account;
auto odd_line = false;
parse_errors = false;
for (orig_lines_it, odd_line;
orig_lines_it != orig_lines_max;
++orig_lines_it, odd_line = !odd_line)
/* Iterate over all parsed lines */
for (parsed_lines_it, odd_line;
parsed_lines_it != parsed_lines_max;
++parsed_lines_it, odd_line = !odd_line)
{
auto orig_line = *orig_lines_it;
auto parsed_line = *parsed_lines_it;
/* Skip current line if:
1. only looking for lines with error AND no error on current line
@ -457,13 +454,13 @@ int GncTxImport::parse_to_trans (Account* account,
2. looking for all lines AND
skip_rows is enabled AND
current line is an odd line */
if ((redo_errors && std::get<1>(orig_line).empty()) ||
if ((redo_errors && std::get<1>(parsed_line).empty()) ||
(!redo_errors && skip_rows && odd_line))
continue;
try
{
parse_line_to_trans (orig_line);
create_transaction (parsed_line);
}
catch (const std::invalid_argument&)
{
@ -473,9 +470,7 @@ int GncTxImport::parse_to_trans (Account* account,
if (std::find(column_types.begin(),column_types.end(), GncTransPropType::BALANCE) !=
column_types.end()) // This is only used if we have one home account
adjust_balances (home_account);
return 0;
adjust_balances ();
}

View File

@ -44,20 +44,13 @@ extern "C" {
#include "gnc-trans-props.hpp"
/* TODO We now sort transactions by date, not line number, so we
* should probably get rid of this struct and uses of it. */
/** Struct pairing a transaction with a line number. This struct is
* used to keep the transactions in order. When rows are separated
* into "valid" and "error" lists (in case some of the rows have cells
* that are unparseable), we want the user to still be able to
* "correct" the error list. If we keep the line numbers of valid
* transactions, we can then put transactions created from the newly
* corrected rows into the right places. */
struct GncCsvTransLine
/** This struct stores a possibly incomplete transaction
* optionally together with its intended balance in case
* the user had selected a balance column. */
struct DraftTransaction
{
Transaction* trans;
gnc_numeric balance; /**< The (supposed) balance after this transaction takes place */
gnc_numeric balance; /**< The expected balance after this transaction takes place */
bool balance_set; /**< true if balance has been set from user data, false otherwise */
};
@ -102,14 +95,21 @@ public:
void load_file (const std::string& filename);
void convert_encoding (const std::string& encoding);
void parse (bool guessColTypes);
int parse_to_trans (Account* account, bool redo_errors);
void tokenize (bool guessColTypes);
/** This function will attempt to convert all tokenized lines into
* transactions using the column types the user has set.
*/
void create_transactions (Account* account, bool redo_errors);
bool check_for_column_type (GncTransPropType type);
std::unique_ptr<GncTokenizer> tokenizer; /**< Will handle file loading/encoding conversion/splitting into fields */
std::vector<parse_line_t> orig_lines; /**< file_str parsed into a two-dimensional array of strings */
std::vector<GncTransPropType> column_types; /**< Vector of values from the GncCsvColumnType enumeration */
std::multimap <time64, GncCsvTransLine*> transactions; /**< List of GncCsvTransLine*s created using orig_lines and column_types */
std::vector<parse_line_t> parsed_lines; /**< source file parsed into a two-dimensional array of strings.
Per line also holds possible error messages and objects with extracted transaction
and split properties. */
std::vector<GncTransPropType> column_types; /**< Vector of values from the GncCsvColumnType enumeration */
std::multimap <time64, <DraftTransaction*> transactions; /**< map of transaction objects created
from parsed_lines and column_types, ordered by date */
int date_format; /**< The format of the text in the date columns from date_format_internal. */
guint start_row; /**< The start row to generate transactions from. */
guint end_row; /**< The end row to generate transactions from. */
@ -118,11 +118,25 @@ public:
bool parse_errors; /**< Indicates whether the last parse_to_trans run had any errors */
private:
void parse_line_to_trans (parse_line_t& orig_line);
void adjust_balances (Account *account);
/** A helper function used by create_transactions. It will attempt
* to convert a single tokenized line into a transaction using
* the column types the user has set.
*/
void create_transaction (parse_line_t& parsed_line);
/** A helper function used by create_transactions. If the input data has
* a balance column (an no deposit and withdrawal columns)
* it will iterate over all created transactions
* to set the split amount(s) based on the desired balance for that line.
*/
void adjust_balances (void);
GncImpFileFormat file_fmt = GncImpFileFormat::UNKNOWN;
Account *home_account = NULL;
/* The variables below are only used during while creating
* transactions. They keep state information during the conversion.
*/
Account *base_account = nullptr;
};