mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
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:
parent
90e5e96f8f
commit
854ee31989
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user