GnuCash  5.6-150-g038405b370+
Modules | Files | Data Structures | Macros | Typedefs | Enumerations | Functions | Variables
Import_Export

Modules

 AqBanking
 

Files

 
file  import-backend.h
 Generic importer backend interface.
 
file  import-commodity-matcher.h
 A Generic commodity matcher/picker.
 
file  import-main-matcher.h
 Transaction matcher main window.
 
file  import-match-picker.h
 The transaction match picker dialog interface.
 
file  import-pending-matches.h
 Tracking container for pending match status.
 
file  import-settings.h
 Import preference handling.
 
file  import-utilities.h
 Utility functions for writing import modules.
 

Data Structures

struct  AccountOnlineMatch
 
struct  AccountPickerDialog
 
struct  GNCImportSelectedMatchInfo
 
struct  GNCImportTransInfo
 
struct  GNCImportMatchInfo
 
struct  GNCImportLastSplitInfo
 
struct  GNCImportMainMatcher
 
class  TreeRowRefDestructor
 
class  RowInfo
 
struct  EntryInfo
 
struct  match_struct
 
struct  GNCImportMatchPicker
 
struct  GNCPendingMatches
 
struct  GNCImportSettings
 
struct  split_record
 
struct  ofx_info
 
struct  InvestmentAcctData
 

Macros

#define STATE_SECTION   "dialogs/import/generic_matcher/account_matcher"
 
#define GNC_PREFS_GROUP   "dialogs.import.generic.account-picker"
 
#define GNCIMPORT_DESC   "desc"
 
#define GNCIMPORT_MEMO   "memo"
 
#define GNCIMPORT_PAYEE   "payee"
 
#define GNC_PREFS_GROUP   "dialogs.import.generic.transaction-list"
 
#define IMPORT_MAIN_MATCHER_CM_CLASS   "transaction-matcher-dialog"
 
#define CSS_INT_REQUIRED_CLASS   "gnc-class-intervention-required"
 
#define CSS_INT_PROB_REQUIRED_CLASS   "gnc-class-intervention-probably-required"
 
#define CSS_INT_NOT_REQUIRED_CLASS   "gnc-class-intervention-not-required"
 
#define G_MOD_IMPORT_MATCHER   "gnc.import.main-matcher"
 
#define GNC_PREFS_GROUP   "dialogs.import.generic.match-picker"
 
#define GNC_PREF_DISPLAY_RECONCILED   "display-reconciled"
 
#define GNC_PREFS_GROUP_IMPORT   "dialogs.import.generic"
 The preferences used by the importer.
 
#define GNC_PREF_ENABLE_SKIP   "enable-skip"
 
#define GNC_PREF_ENABLE_UPDATE   "enable-update"
 
#define GNC_PREF_USE_BAYES   "use-bayes"
 
#define GNC_PREF_ATM_FEE_THRESHOLD   "atm-fee-threshold"
 
#define GNC_PREF_AUTO_CLEAR_THRESHOLD   "auto-clear-threshold"
 
#define GNC_PREF_AUTO_ADD_THRESHOLD   "auto-add-threshold"
 
#define GNC_PREF_MATCH_THRESHOLD   "match-threshold"
 
#define GNC_PREF_MATCH_DATE_THRESHOLD   "match-date-threshold"
 
#define GNC_PREF_MATCH_DATE_NOT_THRESHOLD   "match-date-not-threshold"
 
#define GNC_PREFS_GROUP   "dialogs.log-replay"
 
#define STRING_FIELD_SIZE   256
 
#define GNC_PREFS_GROUP   "dialogs.import.ofx"
 
#define GNC_PREF_AUTO_COMMODITY   "auto-create-commodity"
 

Typedefs

using StrStrMap = std::unordered_map< std::string, std::string >
 
using TreeRowReferencePtr = std::unique_ptr< GtkTreeRowReference, TreeRowRefDestructor >
 
typedef void(* GNCTransactionProcessedCB) (GNCImportTransInfo *trans_info, gboolean imported, gpointer user_data)
 
typedef GHashTable GNCImportPendingMatches
 
typedef struct OfxTransactionData OfxTransactionData
 

Enumerations

enum  GNCImportAction {
  GNCImport_SKIP, GNCImport_ADD, GNCImport_CLEAR, GNCImport_UPDATE,
  GNCImport_LAST_ACTION, GNCImport_INVALID_ACTION
}
 
enum  downloaded_cols {
  DOWNLOADED_COL_DATE_TXT = 0, DOWNLOADED_COL_DATE_INT64, DOWNLOADED_COL_ACCOUNT, DOWNLOADED_COL_AMOUNT,
  DOWNLOADED_COL_AMOUNT_DOUBLE, DOWNLOADED_COL_DESCRIPTION, DOWNLOADED_COL_DESCRIPTION_ORIGINAL, DOWNLOADED_COL_DESCRIPTION_STYLE,
  DOWNLOADED_COL_MEMO, DOWNLOADED_COL_MEMO_ORIGINAL, DOWNLOADED_COL_MEMO_STYLE, DOWNLOADED_COL_NOTES_ORIGINAL,
  DOWNLOADED_COL_ACTION_ADD, DOWNLOADED_COL_ACTION_CLEAR, DOWNLOADED_COL_ACTION_UPDATE, DOWNLOADED_COL_ACTION_INFO,
  DOWNLOADED_COL_ACTION_PIXBUF, DOWNLOADED_COL_DATA, DOWNLOADED_COL_COLOR, DOWNLOADED_COL_ENABLE,
  NUM_DOWNLOADED_COLS, DOWNLOADED_COL_ACCOUNT = 0, DOWNLOADED_COL_DATE, DOWNLOADED_COL_AMOUNT,
  DOWNLOADED_COL_DESCRIPTION, DOWNLOADED_COL_MEMO, DOWNLOADED_COL_BALANCED, DOWNLOADED_COL_INFO_PTR,
  NUM_DOWNLOADED_COLS
}
 
enum  { COMPLETION_LIST_ORIGINAL, COMPLETION_LIST_NORMALIZED_FOLDED, NUM_COMPLETION_COLS }
 
enum  downloaded_cols {
  DOWNLOADED_COL_DATE_TXT = 0, DOWNLOADED_COL_DATE_INT64, DOWNLOADED_COL_ACCOUNT, DOWNLOADED_COL_AMOUNT,
  DOWNLOADED_COL_AMOUNT_DOUBLE, DOWNLOADED_COL_DESCRIPTION, DOWNLOADED_COL_DESCRIPTION_ORIGINAL, DOWNLOADED_COL_DESCRIPTION_STYLE,
  DOWNLOADED_COL_MEMO, DOWNLOADED_COL_MEMO_ORIGINAL, DOWNLOADED_COL_MEMO_STYLE, DOWNLOADED_COL_NOTES_ORIGINAL,
  DOWNLOADED_COL_ACTION_ADD, DOWNLOADED_COL_ACTION_CLEAR, DOWNLOADED_COL_ACTION_UPDATE, DOWNLOADED_COL_ACTION_INFO,
  DOWNLOADED_COL_ACTION_PIXBUF, DOWNLOADED_COL_DATA, DOWNLOADED_COL_COLOR, DOWNLOADED_COL_ENABLE,
  NUM_DOWNLOADED_COLS, DOWNLOADED_COL_ACCOUNT = 0, DOWNLOADED_COL_DATE, DOWNLOADED_COL_AMOUNT,
  DOWNLOADED_COL_DESCRIPTION, DOWNLOADED_COL_MEMO, DOWNLOADED_COL_BALANCED, DOWNLOADED_COL_INFO_PTR,
  NUM_DOWNLOADED_COLS
}
 
enum  matcher_cols {
  MATCHER_COL_CONFIDENCE = 0, MATCHER_COL_CONFIDENCE_PIXBUF, MATCHER_COL_DATE, MATCHER_COL_AMOUNT,
  MATCHER_COL_DESCRIPTION, MATCHER_COL_MEMO, MATCHER_COL_RECONCILED, MATCHER_COL_PENDING,
  MATCHER_COL_INFO_PTR, NUM_MATCHER_COLS
}
 
enum  GNCImportPendingMatchType { GNCImportPending_NONE, GNCImportPending_AUTO, GNCImportPending_MANUAL }
 

Functions

Accountgnc_import_select_account (GtkWidget *parent, const gchar *account_online_id_value, gboolean prompt_on_no_match, const gchar *account_human_description, const gnc_commodity *new_account_default_commodity, GNCAccountType new_account_default_type, Account *default_selection, gboolean *ok_pressed)
 Must be called with a string containing a unique identifier for the account. More...
 
gnc_commodity * gnc_import_select_commodity (const char *cusip, gboolean ask_on_unknown, const char *default_fullname, const char *default_mnemonic)
 Must be called with a string containing a unique identifier for the commodity. More...
 
void on_matcher_ok_clicked (GtkButton *button, GNCImportMainMatcher *info)
 
void on_matcher_cancel_clicked (GtkButton *button, gpointer user_data)
 
bool on_matcher_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
 
void on_matcher_help_clicked (GtkButton *button, gpointer user_data)
 This allows for the transaction help dialog to be started from the assistant button callback. More...
 
void on_matcher_help_close_clicked (GtkButton *button, gpointer user_data)
 
void gnc_gen_trans_list_delete (GNCImportMainMatcher *info)
 Deletes the given object. More...
 
bool gnc_gen_trans_list_empty (GNCImportMainMatcher *info)
 Checks whether there are no transactions to match. More...
 
void gnc_gen_trans_list_show_all (GNCImportMainMatcher *info)
 Shows widgets. More...
 
GNCImportMainMatcher * gnc_gen_trans_list_new (GtkWidget *parent, const gchar *heading, bool all_from_same_account, gint match_date_hardlimit, bool show_all)
 Create a new generic transaction dialog window and return it. More...
 
GNCImportMainMatcher * gnc_gen_trans_assist_new (GtkWidget *parent, GtkWidget *assistant_page, const gchar *heading, bool all_from_same_account, gint match_date_hardlimit)
 Add the Transaction matcher to an existing page of an assistant. More...
 
void gnc_gen_trans_assist_start (GNCImportMainMatcher *info)
 This starts the import process for transaction from an assistant. More...
 
void gnc_gen_trans_list_add_tp_cb (GNCImportMainMatcher *info, GNCTransactionProcessedCB trans_processed_cb, gpointer user_data)
 Add transaction processed callback to the transaction importer. More...
 
bool gnc_gen_trans_list_run (GNCImportMainMatcher *info)
 Run this dialog and return only after the user pressed Ok, Cancel, or closed the window. More...
 
void gnc_gen_trans_list_show_reconcile_after_close_button (GNCImportMainMatcher *info, bool reconcile_after_close, bool active)
 Show and set the reconcile after close check button. More...
 
GtkWidget * gnc_gen_trans_list_get_reconcile_after_close_button (GNCImportMainMatcher *info)
 Returns the reconcile after close check button. More...
 
void gnc_gen_trans_list_add_trans (GNCImportMainMatcher *gui, Transaction *trans)
 Add a newly imported Transaction to the Transaction Importer. More...
 
void gnc_gen_trans_list_add_trans_with_ref_id (GNCImportMainMatcher *gui, Transaction *trans, guint32 ref_id)
 Add a newly imported Transaction to the Transaction Importer and provide an external reference id for it. More...
 
void gnc_gen_trans_list_add_trans_with_split_data (GNCImportMainMatcher *gui, Transaction *trans, GNCImportLastSplitInfo *lsplit)
 Add a newly imported Transaction to the Transaction Importer. More...
 
GtkWidget * gnc_gen_trans_list_widget (GNCImportMainMatcher *info)
 Returns the widget of this dialog. More...
 
GtkWidget * gnc_gen_trans_list_append_text_widget (GNCImportMainMatcher *info)
 Returns the append_text widget of this dialog. More...
 
void gnc_import_match_picker_run_and_close (GtkWidget *parent, GNCImportTransInfo *transaction_info, GNCImportPendingMatches *pending_matches)
 Run a match_picker dialog so that the selected-MatchInfo in the given trans_info is updated accordingly. More...
 
GNCImportPendingMatches * gnc_import_PendingMatches_new (void)
 
void gnc_import_PendingMatches_delete (GNCImportPendingMatches *map)
 
void gnc_import_PendingMatches_add_match (GNCImportPendingMatches *map, GNCImportMatchInfo *match_info, gboolean selected_manually)
 
void gnc_import_PendingMatches_remove_match (GNCImportPendingMatches *map, GNCImportMatchInfo *match_info, gboolean selected_manually)
 
GNCImportPendingMatchType gnc_import_PendingMatches_get_match_type (GNCImportPendingMatches *map, GNCImportMatchInfo *match_info)
 
const char * gnc_import_PendingMatches_get_type_str (GNCImportPendingMatchType type)
 
GNCImportSettings * gnc_import_Settings_new (void)
 Allocates a new GNCImportSettings object, and initialize it with the appropriate user prefs.
 
void gnc_import_Settings_delete (GNCImportSettings *settings)
 Destructor.
 
gboolean gnc_import_trans_has_online_id (Transaction *transaction)
 
gboolean gnc_import_split_has_online_id (Split *split)
 
void gnc_file_log_replay (GtkWindow *parent)
 The gnc_file_log_replay() routine will pop up a standard file selection dialogue asking the user to pick a log file to replay. More...
 
int ofx_proc_statement_cb (struct OfxStatementData data, void *statement_user_data)
 
int ofx_proc_security_cb (const struct OfxSecurityData data, void *security_user_data)
 
int ofx_proc_transaction_cb (OfxTransactionData data, void *user_data)
 
int ofx_proc_account_cb (struct OfxAccountData data, void *account_user_data)
 
void gnc_file_ofx_import (GtkWindow *parent)
 The gnc_file_ofx_import() routine will pop up a standard file selection dialogue asking the user to pick a OFX/QFX file. More...
 
char * libgncmod_ofx_gnc_module_path (void)
 
char * libgncmod_ofx_gnc_module_description (void)
 
int libgncmod_ofx_gnc_module_init (int refcount)
 
int libgncmod_ofx_gnc_module_end (int refcount)
 

Variables

gint GNCPendingMatches::num_manual_matches
 
gint GNCPendingMatches::num_auto_matches
 
int libgncmod_ofx_gnc_module_system_interface = 0
 
int libgncmod_ofx_gnc_module_current = 0
 
int libgncmod_ofx_gnc_module_revision = 0
 
int libgncmod_ofx_gnc_module_age = 0
 

Non-GUI Functions

GdkPixbuf * gen_probability_pixbuf (gint score, GNCImportSettings *settings, GtkWidget *widget)
 This function generates a new pixmap representing a match score. More...
 
void split_find_match (GNCImportTransInfo *trans_info, Split *split, gint display_threshold, gint date_threshold, gint date_not_threshold, double fuzzy_amount_difference)
 The transaction matching heuristics are here. More...
 
gboolean gnc_import_process_trans_item (Account *base_acc, GNCImportTransInfo *trans_info)
 /brief – Processes one match according to its selected action. More...
 
gboolean gnc_import_exists_online_id (Transaction *trans, GHashTable *acct_id_hash)
 Checks whether the given transaction's online_id already exists in its parent account. More...
 
void gnc_import_TransInfo_init_matches (GNCImportTransInfo *trans_info, GNCImportSettings *settings)
 Iterates through all splits of trans_info's originating account match list. More...
 

Getters/Setters for GNCImportTransInfo

GList * gnc_import_TransInfo_get_match_list (const GNCImportTransInfo *info)
 Returns the stored list of possible matches. More...
 
void gnc_import_TransInfo_remove_top_match (GNCImportTransInfo *info)
 Remove the first match in the list of possible matches.
 
Transaction * gnc_import_TransInfo_get_trans (const GNCImportTransInfo *info)
 Returns the transaction of this TransInfo. More...
 
gboolean gnc_import_TransInfo_is_balanced (const GNCImportTransInfo *info)
 Returns if the transaction stored in the TransInfo is currently balanced. More...
 
Split * gnc_import_TransInfo_get_fsplit (const GNCImportTransInfo *info)
 Returns the first split of the transaction of this TransInfo. More...
 
GNCImportMatchInfognc_import_TransInfo_get_selected_match (const GNCImportTransInfo *info)
 Returns the currently selected match in this TransInfo. More...
 
void gnc_import_TransInfo_set_selected_match_info (GNCImportTransInfo *info, GNCImportMatchInfo *match, gboolean selected_manually)
 Sets the currently selected match in this TransInfo. More...
 
gboolean gnc_import_TransInfo_get_match_selected_manually (const GNCImportTransInfo *info)
 Returns if the currently selected match was selected by the user. More...
 
GNCImportAction gnc_import_TransInfo_get_action (const GNCImportTransInfo *info)
 Returns the currently selected action for this TransInfo. More...
 
void gnc_import_TransInfo_set_action (GNCImportTransInfo *info, GNCImportAction action)
 Set the action for this TransInfo. More...
 
Accountgnc_import_TransInfo_get_destacc (const GNCImportTransInfo *info)
 Returns the 'other account' of this transaction. More...
 
void gnc_import_TransInfo_set_destacc (GNCImportTransInfo *info, Account *acc, gboolean selected_manually)
 Set the 'other account' of this transaction (used for auto-balance if needed). More...
 
gboolean gnc_import_TransInfo_get_destacc_selected_manually (const GNCImportTransInfo *info)
 Returns if the currently selected destination account for auto-matching was selected by the user. More...
 
guint32 gnc_import_TransInfo_get_ref_id (const GNCImportTransInfo *info)
 Returns the reference id for this TransInfo. More...
 
void gnc_import_TransInfo_set_ref_id (GNCImportTransInfo *info, guint32 ref_id)
 Set the reference id for this TransInfo. More...
 
gnc_numeric gnc_import_TransInfo_get_price (const GNCImportTransInfo *info)
 Returns the exchange rate for this TransInfo. More...
 
void gnc_import_TransInfo_set_price (GNCImportTransInfo *info, gnc_numeric lprice)
 Set the exchange rate for this TransInfo. More...
 
gnc_numeric gnc_import_TransInfo_get_dest_amount (const GNCImportTransInfo *info)
 Returns the destination split amount for this TransInfo. More...
 
gnc_numeric gnc_import_TransInfo_get_dest_value (const GNCImportTransInfo *info)
 Returns the destination split value for this TransInfo. More...
 
void gnc_import_TransInfo_set_last_split_info (GNCImportTransInfo *info, GNCImportLastSplitInfo *lsplit)
 Sets additional parameters to be used to generate the closing split.
 
void gnc_import_TransInfo_set_append_text (GNCImportTransInfo *info, gboolean append_text)
 Set the append_text for this TransInfo. More...
 
void gnc_import_TransInfo_delete (GNCImportTransInfo *info)
 Destructor.
 
GNCImportTransInfo * gnc_import_TransInfo_new (Transaction *trans, Account *base_acc)
 Create a new object of GNCImportTransInfo here. More...
 

Getters/Setters for GNCImportMatchInfo

Split * gnc_import_MatchInfo_get_split (const GNCImportMatchInfo *info)
 Get the split ('this-side split') of this MatchInfo. More...
 
gint gnc_import_MatchInfo_get_probability (const GNCImportMatchInfo *info)
 Get the probability (confidence level) of this MatchInfo. More...
 

Getters/Setters for GNCImportSettings

double gnc_import_Settings_get_fuzzy_amount (GNCImportSettings *settings)
 Return the allowed amount range for fuzzy amount matching. More...
 
gboolean gnc_import_Settings_get_action_skip_enabled (GNCImportSettings *settings)
 Return the selected action is enable state.
 
gboolean gnc_import_Settings_get_action_add_enabled (GNCImportSettings *settings)
 Return the selected action is enable state.
 
gboolean gnc_import_Settings_get_action_update_enabled (GNCImportSettings *settings)
 Return the selected action is enable state.
 
gboolean gnc_import_Settings_get_action_clear_enabled (GNCImportSettings *settings)
 Return the selected action is enable state.
 
gint gnc_import_Settings_get_clear_threshold (GNCImportSettings *settings)
 Return the selected threshold.
 
gint gnc_import_Settings_get_add_threshold (GNCImportSettings *settings)
 Return the selected threshold.
 
gint gnc_import_Settings_get_display_threshold (GNCImportSettings *settings)
 Return the selected threshold.
 
gint gnc_import_Settings_get_date_threshold (GNCImportSettings *settings)
 
gint gnc_import_Settings_get_date_not_threshold (GNCImportSettings *settings)
 
void gnc_import_Settings_set_match_date_hardlimit (GNCImportSettings *s, gint m)
 
gint gnc_import_Settings_get_match_date_hardlimit (const GNCImportSettings *settings)
 Returns the hard-limiting number of days that a matching split may differ. More...
 

Setter-getters

Setter and getter functions for the online_id field for Splits.

gchar * gnc_import_get_acc_online_id (Account *account)
 
void gnc_import_set_acc_online_id (Account *account, const gchar *id)
 
gchar * gnc_import_get_trans_online_id (Transaction *transaction)
 
void gnc_import_set_trans_online_id (Transaction *transaction, const gchar *id)
 
gchar * gnc_import_get_split_online_id (Split *split)
 
void gnc_import_set_split_online_id (Split *split, const gchar *id)
 

Detailed Description

Function Documentation

◆ gen_probability_pixbuf()

GdkPixbuf * gen_probability_pixbuf ( gint  score,
GNCImportSettings *  settings,
GtkWidget *  widget 
)

This function generates a new pixmap representing a match score.

It is a series of vertical bars of different colors. -Below or at the add_threshold the bars are red -Above or at the clear_threshold the bars are green -Between the two threshold the bars are yellow

Parameters
scoreThe score for which to generate a pixmap.
settingsThe user settings from which to get the threshold
widgetThe parent widget in which the pixmap will eventually be added. Will be used to generate the colormap.

Definition at line 360 of file import-backend.cpp.

361 {
362  constexpr gint height = 15;
363  constexpr gint width_each_bar = 7;
364  constexpr gint width_first_bar = 1;
365  constexpr gint num_colors = 5;
366  constexpr size_t xpm_size = 2 + num_colors + height;
367  gchar * xpm[xpm_size];
368 
369  g_assert(settings);
370  g_assert(widget);
371 
372  auto score = std::max (0, score_original);
373 
374  /* Add size definition to xpm */
375  xpm[0] = g_strdup_printf("%d%s%d%s%d%s", (width_each_bar * score) + width_first_bar/*width*/, " ", height, " ", num_colors, " 1"/*characters per pixel*/);
376 
377  /* Define used colors */
378  xpm[1] = g_strdup(" c None");
379  xpm[2] = g_strdup("g c green");
380  xpm[3] = g_strdup("y c yellow");
381  xpm[4] = g_strdup("r c red");
382  xpm[5] = g_strdup("b c black");
383 
384  auto add_threshold = gnc_import_Settings_get_add_threshold(settings);
385  auto clear_threshold = gnc_import_Settings_get_clear_threshold(settings);
386  for (int i = 0; i < height; i++)
387  {
388  xpm[num_colors+1+i] = g_new0(char, (width_each_bar * score) + width_first_bar + 1);
389  for (int j = 0; j <= score; j++)
390  {
391  if (j == 0)
392  strcat(xpm[num_colors+1+i], "b");
393  else if (i == 0 || i == height - 1)
394  strcat(xpm[num_colors+1+i], "bbbbbb ");
395  else if (j <= add_threshold)
396  strcat(xpm[num_colors+1+i], "brrrrb ");
397  else if (j >= clear_threshold)
398  strcat(xpm[num_colors+1+i], "bggggb ");
399  else
400  strcat(xpm[num_colors+1+i], "byyyyb ");
401  }
402  }
403  GError *err = nullptr;
404  std::string xpm_str = "/* XPM */\nstatic char * XFACE[] = {\n";
405 
406  for (auto i = 0UL; i < xpm_size - 1; i++)
407  {
408  xpm_str += "\"";
409  xpm_str += xpm[i];
410  xpm_str += "\",\n";
411  g_free(xpm[i]);
412  }
413  xpm_str += "};";
414 
415  auto gstream = g_memory_input_stream_new_from_data(xpm_str.c_str(), -1,
416  nullptr);
417  auto retval =
418  gdk_pixbuf_new_from_stream(G_INPUT_STREAM(gstream), nullptr, &err);
419  g_object_unref(gstream);
420 
421  if (!retval && err)
422  PERR("Failed to create pixbuf from XPM data: %s", err->message);
423 
424  return retval;
425 }
gint gnc_import_Settings_get_clear_threshold(GNCImportSettings *settings)
Return the selected threshold.
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
gint gnc_import_Settings_get_add_threshold(GNCImportSettings *settings)
Return the selected threshold.

◆ gnc_file_log_replay()

void gnc_file_log_replay ( GtkWindow *  parent)

The gnc_file_log_replay() routine will pop up a standard file selection dialogue asking the user to pick a log file to replay.

If one is selected the .log file is opened and read. Its contents are then silently merged in the current log file.

Definition at line 542 of file gnc-log-replay.cpp.

543 {
544  char *selected_filename;
545  char *default_dir;
546  char read_buf[256];
547  char *read_retval;
548  GtkFileFilter *filter;
549  FILE *log_file;
550  const char * record_start_str = "===== START";
551  /* NOTE: This string must match src/engine/TransLog.c (sans newline) */
552  const char * expected_header = "mod\ttrans_guid\tsplit_guid\ttime_now\t"
553  "date_entered\tdate_posted\tacc_guid\tacc_name\tnum\tdescription\t"
554  "notes\tmemo\taction\treconciled\tamount\tvalue\tdate_reconciled";
555 
556  // qof_log_set_level(GNC_MOD_IMPORT, QOF_LOG_DEBUG);
557  ENTER(" ");
558 
559  /* Don't log the log replay. This would only result in redundant logs */
560  xaccLogDisable();
561 
562  default_dir = gnc_get_default_directory(GNC_PREFS_GROUP);
563 
564  filter = gtk_file_filter_new();
565  gtk_file_filter_set_name(filter, "*.log");
566  gtk_file_filter_add_pattern(filter, "*.[Ll][Oo][Gg]");
567  selected_filename = gnc_file_dialog(parent,
568  _("Select a .log file to replay"),
569  g_list_prepend(NULL, filter),
570  default_dir,
571  GNC_FILE_DIALOG_OPEN);
572  g_free(default_dir);
573 
574  if (selected_filename != NULL)
575  {
576  /* Remember the directory as the default. */
577  default_dir = g_path_get_dirname(selected_filename);
578  gnc_set_default_directory(GNC_PREFS_GROUP, default_dir);
579  g_free(default_dir);
580 
581  /*strncpy(file,selected_filename, 255);*/
582  DEBUG("Filename found: %s", selected_filename);
583  if (xaccFileIsCurrentLog(selected_filename))
584  {
585  g_warning("Cannot open the current log file: %s", selected_filename);
586  gnc_error_dialog(NULL,
587  /* Translators: %s is the file name. */
588  _("Cannot open the current log file: %s"),
589  selected_filename);
590  }
591  else
592  {
593  DEBUG("Opening selected file");
594  log_file = g_fopen(selected_filename, "r");
595  if (!log_file || ferror(log_file) != 0)
596  {
597  int err = errno;
598  perror("File open failed");
599  /* Translators: First argument is the filename,
600  * second argument is the error.
601  */
602  gnc_error_dialog(NULL,
603  _("Failed to open log file: %s: %s"),
604  selected_filename,
605  strerror(err));
606  }
607  else
608  {
609  if ((read_retval = fgets(read_buf, sizeof(read_buf), log_file)) == NULL)
610  {
611  DEBUG("Read error or EOF");
612  gnc_info_dialog(NULL, "%s",
613  _("The log file you selected was empty."));
614  }
615  else
616  {
617  if (strncmp(expected_header, read_buf, strlen(expected_header)) != 0)
618  {
619  PERR("File header not recognised:\n%s", read_buf);
620  PERR("Expected:\n%s", expected_header);
621  gnc_error_dialog(NULL, "%s",
622  _("The log file you selected cannot be read. "
623  "The file header was not recognized."));
624  }
625  else
626  {
627  do
628  {
629  read_retval = fgets(read_buf, sizeof(read_buf), log_file);
630  /*DEBUG("Chunk read: %s",read_retval);*/
631  if (read_retval && strncmp(record_start_str, read_buf, strlen(record_start_str)) == 0) /* If a record started */
632  {
633  process_trans_record(log_file);
634  }
635  }
636  while (feof(log_file) == 0);
637  }
638  }
639  fclose(log_file);
640  }
641  }
642  g_free(selected_filename);
643  }
644  /* Start logging again */
645  xaccLogEnable();
646 
647  LEAVE("");
648 }
void xaccLogDisable(void)
document me
Definition: TransLog.cpp:96
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
gboolean xaccFileIsCurrentLog(const gchar *name)
Test a filename to see if it is the name of the current logfile.
Definition: TransLog.cpp:141
void xaccLogEnable(void)
document me
Definition: TransLog.cpp:100

◆ gnc_file_ofx_import()

void gnc_file_ofx_import ( GtkWindow *  parent)

The gnc_file_ofx_import() routine will pop up a standard file selection dialogue asking the user to pick a OFX/QFX file.

If one is selected the OFX file is opened and read. Its contents are merged into the existing session (if any). The current session continues to remain open for editing.

Definition at line 1453 of file gnc-ofx-import.cpp.

1454 {
1455  extern int ofx_PARSER_msg;
1456  extern int ofx_DEBUG_msg;
1457  extern int ofx_WARNING_msg;
1458  extern int ofx_ERROR_msg;
1459  extern int ofx_INFO_msg;
1460  extern int ofx_STATUS_msg;
1461  GSList* selected_filenames = NULL;
1462  char *default_dir;
1463  GList *filters = NULL;
1464  ofx_info* info = NULL;
1465  GtkFileFilter* filter = gtk_file_filter_new ();
1466 
1467 
1468  ofx_PARSER_msg = false;
1469  ofx_DEBUG_msg = false;
1470  ofx_WARNING_msg = true;
1471  ofx_ERROR_msg = true;
1472  ofx_INFO_msg = true;
1473  ofx_STATUS_msg = false;
1474 
1475  DEBUG("gnc_file_ofx_import(): Begin...\n");
1476 
1477  default_dir = gnc_get_default_directory(GNC_PREFS_GROUP);
1478  gtk_file_filter_set_name (filter, _("Open/Quicken Financial Exchange file (*.ofx, *.qfx)"));
1479  gtk_file_filter_add_pattern (filter, "*.[oqOQ][fF][xX]");
1480  filters = g_list_prepend( filters, filter );
1481 
1482  selected_filenames = gnc_file_dialog_multi (parent,
1483  _("Select one or multiple OFX/QFX file(s) to process"),
1484  filters,
1485  default_dir,
1486  GNC_FILE_DIALOG_IMPORT);
1487  g_free(default_dir);
1488 
1489  if (selected_filenames)
1490  {
1491  /* Remember the directory as the default. */
1492  default_dir = g_path_get_dirname(static_cast<char*>(selected_filenames->data));
1493  gnc_set_default_directory(GNC_PREFS_GROUP, default_dir);
1494  g_free(default_dir);
1495 
1496  /* Look up the needed preferences */
1497  auto_create_commodity =
1498  gnc_prefs_get_bool (GNC_PREFS_GROUP_IMPORT, GNC_PREF_AUTO_COMMODITY);
1499 
1500  DEBUG("Opening selected file(s)");
1501  // Create the structure that holds the list of files to process and the statement info.
1502  info = g_new(ofx_info,1);
1503  info->num_trans_processed = 0;
1504  info->statement = NULL;
1505  info->last_investment_account = NULL;
1506  info->last_import_account = NULL;
1507  info->last_income_account = NULL;
1508  info->parent = parent;
1509  info->run_reconcile = FALSE;
1510  info->file_list = selected_filenames;
1511  info->trans_list = NULL;
1512  info->response = 0;
1513  // Call the aux import function.
1514  gnc_file_ofx_import_process_file (info);
1515  }
1516 }
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
#define GNC_PREFS_GROUP_IMPORT
The preferences used by the importer.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.

◆ gnc_gen_trans_assist_new()

GNCImportMainMatcher * gnc_gen_trans_assist_new ( GtkWidget *  parent,
GtkWidget *  assistant_page,
const gchar *  heading,
bool  all_from_same_account,
gint  match_date_hardlimit 
)

Add the Transaction matcher to an existing page of an assistant.

Must be called with the parent widget, ie. a vbox that the transaction matcher will be packed into. The data structure GNCImportMainMatcher is returned.

Parameters
parentThe parent widget
assistant_pageThe parent widget. This is the place the transaction matcher will be packed into.
headingThe heading label in the Importer window. May be NULL.
all_from_same_accountSet this to TRUE if ALL the transaction that will be added with gnc_gen_trans_list_add_trans are from the same source account. This will cause the account column to be hidden.
match_date_hardlimitThe number of days that a matching split may differ from the given transaction before it is discarded immediately. In other words, any split that is more distant from the given transaction than this match_date_hardlimit days will be ignored altogether. For use cases without paper checks (e.g. HBCI), values like 14 (days) might be appropriate, whereas for use cases with paper checks (e.g. OFX, QIF), values like 42 (days) seem more appropriate.
Returns
A pointer to the GNCImportMainMatcher which has been setup.

Definition at line 1810 of file import-main-matcher.cpp.

1815 {
1816  GNCImportMainMatcher *info = g_new0 (GNCImportMainMatcher, 1);
1817  info->main_widget = GTK_WIDGET(parent);
1818 
1819  /* load the interface */
1820  GtkBuilder *builder = gtk_builder_new ();
1821  gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher_content");
1822 
1823  /* Pack content into Assistant page widget */
1824  GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_content"));
1825  g_assert (box != NULL);
1826  gtk_box_pack_start (GTK_BOX(assistant_page), box, true, true, 6);
1827 
1828  // Set the name for this dialog so it can be easily manipulated with css
1829  gtk_widget_set_name (GTK_WIDGET(box), "gnc-id-import-transaction-content");
1830 
1831  /* setup the common parts */
1832  gnc_gen_trans_common_setup (info, parent, builder, heading,
1833  all_from_same_account, match_date_hardlimit);
1834 
1835  return info;
1836 }

◆ gnc_gen_trans_assist_start()

void gnc_gen_trans_assist_start ( GNCImportMainMatcher *  info)

This starts the import process for transaction from an assistant.

assistant button callback.

Parameters
info.A pointer to the GNCImportMainMatcher structure

Definition at line 1839 of file import-main-matcher.cpp.

1840 {
1841  on_matcher_ok_clicked (NULL, info);
1842 }

◆ gnc_gen_trans_list_add_tp_cb()

void gnc_gen_trans_list_add_tp_cb ( GNCImportMainMatcher *  info,
GNCTransactionProcessedCB  trans_processed_cb,
gpointer  user_data 
)

Add transaction processed callback to the transaction importer.

Parameters
infoThe Transaction Importer to use.
trans_processed_cbThe callback function.

Definition at line 1849 of file import-main-matcher.cpp.

1852 {
1853  info->user_data = user_data;
1854  info->transaction_processed_cb = trans_processed_cb;
1855 }

◆ gnc_gen_trans_list_add_trans()

void gnc_gen_trans_list_add_trans ( GNCImportMainMatcher *  gui,
Transaction *  trans 
)

Add a newly imported Transaction to the Transaction Importer.

The Importer takes over ownership of the passed transaction.

Parameters
guiThe Transaction Importer to use.
transThe Transaction to add. The must contain at least one split, and this split must have been associated with an account Only the first split will be used for matching. The transaction must NOT be committed. The Importer takes over ownership of the passed transaction.

Definition at line 2286 of file import-main-matcher.cpp.

2287 {
2288  gnc_gen_trans_list_add_trans_internal (gui, trans, 0, NULL);
2289 }

◆ gnc_gen_trans_list_add_trans_with_ref_id()

void gnc_gen_trans_list_add_trans_with_ref_id ( GNCImportMainMatcher *  gui,
Transaction *  trans,
guint32  ref_id 
)

Add a newly imported Transaction to the Transaction Importer and provide an external reference id for it.

The Importer takes over ownership of the passed transaction.

Parameters
guiThe Transaction Importer to use.
transThe Transaction to add. The must contain at least one split, and this split must have been associated with an account Only the first split will be used for matching. The transaction must NOT be committed. The Importer takes over ownership of the passed transaction.
ref_idReference id which links an external object to the transaction.

Definition at line 2292 of file import-main-matcher.cpp.

2293 {
2294  gnc_gen_trans_list_add_trans_internal (gui, trans, ref_id, NULL);
2295 }

◆ gnc_gen_trans_list_add_trans_with_split_data()

void gnc_gen_trans_list_add_trans_with_split_data ( GNCImportMainMatcher *  gui,
Transaction *  trans,
GNCImportLastSplitInfo lsplit 
)

Add a newly imported Transaction to the Transaction Importer.

The Importer takes over ownership of the passed transaction.

Parameters
guiThe Transaction Importer to use.
transThe Transaction to add. The must contain at least one split, and this split must have been associated with an account Only the first split will be used for matching. The transaction must NOT be committed. The Importer takes over ownership of the passed transaction.
lsplitStruct with additional parameters that may be used to generate the final split.

Definition at line 2297 of file import-main-matcher.cpp.

2300 {
2301  gnc_gen_trans_list_add_trans_internal (gui, trans, 0, lsplit);
2302 }

◆ gnc_gen_trans_list_append_text_widget()

GtkWidget * gnc_gen_trans_list_append_text_widget ( GNCImportMainMatcher *  info)

Returns the append_text widget of this dialog.

Parameters
infoA pointer to the GNCImportMainMatcher structure.
Returns
A GtkWidget pointer to the append_text widget.

Definition at line 2471 of file import-main-matcher.cpp.

2472 {
2473  g_assert (info);
2474  return info->append_text;
2475 }

◆ gnc_gen_trans_list_delete()

void gnc_gen_trans_list_delete ( GNCImportMainMatcher *  info)

Deletes the given object.

Definition at line 203 of file import-main-matcher.cpp.

204 {
205 
206  if (info == NULL)
207  return;
208 
209  GtkTreeModel *model = gtk_tree_view_get_model (info->view);
210  GtkTreeIter iter;
211  if (gtk_tree_model_get_iter_first (model, &iter))
212  {
213  do
214  {
215  GNCImportTransInfo *trans_info;
216  gtk_tree_model_get (model, &iter,
217  DOWNLOADED_COL_DATA, &trans_info,
218  -1);
219 
220  if (info->transaction_processed_cb)
221  {
222  info->transaction_processed_cb (trans_info, false,
223  info->user_data);
224  }
225  }
226  while (gtk_tree_model_iter_next (model, &iter));
227  }
228 
229  if (GTK_IS_DIALOG(info->main_widget))
230  {
231  gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(info->main_widget));
232  gnc_import_Settings_delete (info->user_settings);
233  gnc_unregister_gui_component (info->id);
234  gtk_widget_destroy (GTK_WIDGET(info->main_widget));
235  }
236  else
237  gnc_import_Settings_delete (info->user_settings);
238 
239  g_slist_free_full (info->temp_trans_list, (GDestroyNotify) gnc_import_TransInfo_delete);
240  info->temp_trans_list = NULL;
241 
242  // We've deferred balance computations on many accounts. Let's do it now that we're done.
243  update_all_balances (info);
244 
245  gnc_import_PendingMatches_delete (info->pending_matches);
246  g_hash_table_destroy (info->acct_id_hash);
247  g_hash_table_destroy (info->desc_hash);
248  g_hash_table_destroy (info->notes_hash);
249  g_hash_table_destroy (info->memo_hash);
250  info->colormap.~StrStrMap();
251 
252  g_list_free_full (info->new_strings, (GDestroyNotify)g_free);
253 
254  g_free (info);
255 
256  if (!gnc_gui_refresh_suspended ())
257  gnc_gui_refresh_all ();
258 }
void gnc_import_TransInfo_delete(GNCImportTransInfo *info)
Destructor.
void gnc_import_Settings_delete(GNCImportSettings *settings)
Destructor.

◆ gnc_gen_trans_list_empty()

bool gnc_gen_trans_list_empty ( GNCImportMainMatcher *  info)

Checks whether there are no transactions to match.

Parameters
infoA pointer to the GNCImportMainMatcher structure.
Returns
A boolean indicating whether the transaction list is empty.

Definition at line 261 of file import-main-matcher.cpp.

262 {
263  g_assert (info);
264 
265  GtkTreeIter iter;
266  GtkTreeModel *model = gtk_tree_view_get_model (info->view);
267  // Check that both the tree model and the temporary list are empty.
268  return !gtk_tree_model_get_iter_first (model, &iter) && !info->temp_trans_list;
269 }

◆ gnc_gen_trans_list_get_reconcile_after_close_button()

GtkWidget * gnc_gen_trans_list_get_reconcile_after_close_button ( GNCImportMainMatcher *  info)

Returns the reconcile after close check button.

Parameters
infoA pointer to the GNCImportMainMatcher structure.
Returns
The check button.

Definition at line 2250 of file import-main-matcher.cpp.

2251 {
2252  return info->reconcile_after_close;
2253 }

◆ gnc_gen_trans_list_new()

GNCImportMainMatcher * gnc_gen_trans_list_new ( GtkWidget *  parent,
const gchar *  heading,
bool  all_from_same_account,
gint  match_date_hardlimit,
bool  show_all 
)

Create a new generic transaction dialog window and return it.

Parameters
parentThe parent GtkWidget. May be NULL.
headingThe heading label in the Importer window. May be NULL.
all_from_same_accountSet this to TRUE if ALL the transaction that will be added with gnc_gen_trans_list_add_trans are from the same source account. This will cause the account column to be hidden.
match_date_hardlimitThe number of days that a matching split may differ from the given transaction before it is discarded immediately. In other words, any split that is more distant from the given transaction than this match_date_hardlimit days will be ignored altogether. For use cases without paper checks (e.g. HBCI), values like 14 (days) might be appropriate, whereas for use cases with paper checks (e.g. OFX, QIF), values like 42 (days) seem more appropriate.
show_allif true, all widgets are shown
Returns
A pointer to the GNCImportMainMatcher which has been setup.

Definition at line 1756 of file import-main-matcher.cpp.

1761 {
1762  GNCImportMainMatcher *info = g_new0 (GNCImportMainMatcher, 1);
1763 
1764  /* Initialize the GtkDialog. */
1765  GtkBuilder *builder = gtk_builder_new ();
1766  gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher_dialog");
1767  gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher_content");
1768 
1769  info->main_widget = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_dialog"));
1770  g_assert (info->main_widget != NULL);
1771 
1772  /* Pack the content into the dialog vbox */
1773  GtkWidget *pbox = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_vbox"));
1774  GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_content"));
1775  gtk_box_pack_start (GTK_BOX(pbox), box, true, true, 0);
1776 
1777  // Set the name for this dialog so it can be easily manipulated with css
1778  gtk_widget_set_name (GTK_WIDGET(info->main_widget), "gnc-id-import-matcher-transactions");
1779  gtk_widget_set_name (GTK_WIDGET(box), "gnc-id-import-transaction-content");
1780  gnc_widget_style_context_add_class (GTK_WIDGET(info->main_widget), "gnc-class-imports");
1781 
1782  /* setup the common parts */
1783  gnc_gen_trans_common_setup (info, parent, builder, heading,
1784  all_from_same_account, match_date_hardlimit);
1785 
1786  if (parent)
1787  gtk_window_set_transient_for (GTK_WINDOW(info->main_widget), GTK_WINDOW(parent));
1788 
1789  gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(info->main_widget), GTK_WINDOW(parent));
1790 
1791  if (show_all)
1792  gtk_widget_show_all (GTK_WIDGET(info->main_widget));
1793 
1794  // Register this UI, it needs to be closed when the session is closed.
1795  info->id = gnc_register_gui_component (IMPORT_MAIN_MATCHER_CM_CLASS,
1796  NULL, /* no refresh handler */
1797  (GNCComponentCloseHandler)gnc_gen_trans_list_delete,
1798  info);
1799  // This ensure this dialog is closed when the session is closed.
1800  gnc_gui_component_set_session (info->id, gnc_get_current_session());
1801 
1802  return info;
1803 }
void gnc_gen_trans_list_delete(GNCImportMainMatcher *info)
Deletes the given object.

◆ gnc_gen_trans_list_run()

bool gnc_gen_trans_list_run ( GNCImportMainMatcher *  info)

Run this dialog and return only after the user pressed Ok, Cancel, or closed the window.

This means that all actual importing will have been finished upon returning.

Parameters
infoA pointer to the GNCImportMainMatcher structure.
Returns
The boolean return value of the dialog run.

Definition at line 1858 of file import-main-matcher.cpp.

1859 {
1860  /* DEBUG("Begin"); */
1861  bool result = gtk_dialog_run (GTK_DIALOG (info->main_widget));
1862  /* DEBUG("Result was %d", result); */
1863 
1864  /* No destroying here since the dialog was already destroyed through
1865  the ok_clicked handlers. */
1866 
1867  return result;
1868 }

◆ gnc_gen_trans_list_show_all()

void gnc_gen_trans_list_show_all ( GNCImportMainMatcher *  info)

Shows widgets.

Parameters
infoA pointer to the GNCImportMainMatcher structure.

Definition at line 500 of file import-main-matcher.cpp.

501 {
502  g_assert (info);
503 
504  // Set initial state of Append checkbox to same as last import for this account.
505  // Get the import account from the first split in first transaction.
506  GSList *temp_trans_list = info->temp_trans_list;
507  if (!temp_trans_list)
508  {
509  gnc_info_dialog (GTK_WINDOW (info->main_widget), "%s", _("No new transactions were found in this import."));
510  return;
511  }
512  auto trans_info = static_cast<GNCImportTransInfo *>(temp_trans_list->data);
513  Split *first_split = gnc_import_TransInfo_get_fsplit (trans_info);
514  Account *account = xaccSplitGetAccount(first_split);
515  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (info->append_text),
516  xaccAccountGetAppendText(account));
517 
518  gnc_gen_trans_list_create_matches (info);
519  load_hash_tables (info);
520  resolve_conflicts (info);
521  gtk_widget_show_all (GTK_WIDGET(info->main_widget));
522  gnc_gen_trans_list_show_accounts_column (info);
523 }
gboolean xaccAccountGetAppendText(const Account *acc)
Get the "import-append-text" flag for an account.
Definition: Account.cpp:4090
STRUCTS.
Split * gnc_import_TransInfo_get_fsplit(const GNCImportTransInfo *info)
Returns the first split of the transaction of this TransInfo.
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
Definition: gmock-Split.cpp:53

◆ gnc_gen_trans_list_show_reconcile_after_close_button()

void gnc_gen_trans_list_show_reconcile_after_close_button ( GNCImportMainMatcher *  info,
bool  reconcile_after_close,
bool  active 
)

Show and set the reconcile after close check button.

Parameters
infoA pointer to the GNCImportMainMatcher structure.
reconcile_after_closeA bool that shows or hides the button.
activeA bool to set or clear the check button.

Definition at line 2241 of file import-main-matcher.cpp.

2244 {
2245  gtk_widget_set_visible (info->reconcile_after_close, reconcile_after_close);
2246  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (info->reconcile_after_close), active);
2247 }

◆ gnc_gen_trans_list_widget()

GtkWidget * gnc_gen_trans_list_widget ( GNCImportMainMatcher *  info)

Returns the widget of this dialog.

Parameters
infoA pointer to the GNCImportMainMatcher structure.
Returns
A GtkWidget pointer to the dialog's widget.

Definition at line 2464 of file import-main-matcher.cpp.

2465 {
2466  g_assert (info);
2467  return info->main_widget;
2468 }

◆ gnc_import_exists_online_id()

gboolean gnc_import_exists_online_id ( Transaction *  trans,
GHashTable *  acct_id_hash 
)

Checks whether the given transaction's online_id already exists in its parent account.

The given transaction has to be open for editing. If a matching online_id exists, the transaction is destroyed (!) and TRUE is returned, otherwise FALSE is returned.

Parameters
transThe transaction for which to check for an existing online_id.

Definition at line 1052 of file import-backend.cpp.

1053 {
1054 
1055  /* Look for an online_id in the first split */
1056  auto source_split = xaccTransGetSplit(trans, 0);
1057  g_assert(source_split);
1058 
1059  auto source_online_id = gnc_import_get_split_online_id (source_split);
1060 
1061  // No online id, no point in continuing. We'd crash if we tried.
1062  if (!source_online_id)
1063  return false;
1064 
1065  // Create a hash per account of a hash of all split IDs. Then the
1066  // test below will be fast if we have many transactions to import.
1067  auto dest_acct = xaccSplitGetAccount (source_split);
1068 
1069  auto online_id_hash = static_cast<GHashTable*>(g_hash_table_lookup (acct_id_hash, dest_acct));
1070 
1071  if (!online_id_hash)
1072  {
1073  online_id_hash = hash_account_online_ids (dest_acct);
1074  g_hash_table_insert (acct_id_hash, dest_acct, online_id_hash);
1075  }
1076 
1077  auto online_id_exists = g_hash_table_contains (online_id_hash, source_online_id);
1078  if (online_id_exists)
1079  {
1080  auto date_str = qof_print_date(xaccTransGetDate(trans));
1081  DEBUG("Transaction with online ID %s already exists, date: %s", source_online_id, date_str);
1082  g_free (date_str);
1083  }
1084  g_free (source_online_id);
1085  return online_id_exists;
1086 }
Split * xaccTransGetSplit(const Transaction *trans, int i)
Return a pointer to the indexed split in this transaction&#39;s split list.
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
char * qof_print_date(time64 secs)
Convenience; calls through to qof_print_date_dmy_buff().
Definition: gnc-date.cpp:610
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
Definition: gmock-Split.cpp:53

◆ gnc_import_match_picker_run_and_close()

void gnc_import_match_picker_run_and_close ( GtkWidget *  parent,
GNCImportTransInfo *  transaction_info,
GNCImportPendingMatches *  pending_matches 
)

Run a match_picker dialog so that the selected-MatchInfo in the given trans_info is updated accordingly.

Run a match_picker dialog where the user should pick the best match for 'one' given transaction, so that the selected-MatchInfo in the given trans_info is updated accordingly.

This functions will only return after the user clicked Ok, Cancel, or Window-Close.

This functions will only return after the user clicked Ok, Cancel, or Window-Close.

The dialog uses the same functionality as the one created through gnc_import_add_trans(), except that its two listviews are shown above one another, and the listview of downloaded transactions shows only one transaction, namely, the given trans_info.

This function is used from the gnc-gen-transaction code.

Parameters
parentThe parent widget
transaction_infoThe TransInfo for which the user is supposed to pick a matching transaction.
pending_matchesList of transactions

Definition at line 432 of file import-match-picker.cpp.

434 {
435  GNCImportMatchPicker *matcher;
436  gint response;
437  GNCImportMatchInfo *old;
438  gboolean old_selected_manually;
439  g_assert (transaction_info);
440 
441  /* Create a new match_picker, even though it's stored in a
442  transmatcher struct :-) */
443  matcher = g_new0(GNCImportMatchPicker, 1);
444 
445  matcher->pending_matches = pending_matches;
446 
447  /* DEBUG("Init match_picker"); */
448  init_match_picker_gui(parent, matcher);
449 
450  /* Append this single transaction to the view and select it */
451  downloaded_transaction_append(matcher, transaction_info);
452 
453  old = gnc_import_TransInfo_get_selected_match (transaction_info);
454  old_selected_manually =
456 
457  /* Let this dialog run and close. */
458  /*DEBUG("Right before run and close");*/
459  gtk_window_set_modal(GTK_WINDOW(matcher->transaction_matcher), TRUE);
460  response = gtk_dialog_run (GTK_DIALOG (matcher->transaction_matcher));
461 
462  gnc_save_window_size(GNC_PREFS_GROUP,
463  GTK_WINDOW (matcher->transaction_matcher));
464  gtk_widget_destroy (matcher->transaction_matcher);
465  /*DEBUG("Right after run and close");*/
466  /* DEBUG("Response was %d.", response); */
467  if (response == GTK_RESPONSE_OK && matcher->selected_match_info != old)
468  {
469  /* OK was pressed */
471  matcher->selected_match_info,
472  TRUE);
473 
474  gnc_import_PendingMatches_remove_match (pending_matches,
475  old,
476  old_selected_manually);
477  gnc_import_PendingMatches_add_match (pending_matches,
478  matcher->selected_match_info,
479  TRUE);
480  }
481  gnc_import_Settings_delete (matcher->user_settings);
482  g_free (matcher);
483 }
void gnc_import_TransInfo_set_selected_match_info(GNCImportTransInfo *info, GNCImportMatchInfo *match, gboolean selected_manually)
Sets the currently selected match in this TransInfo.
void gnc_import_Settings_delete(GNCImportSettings *settings)
Destructor.
gboolean gnc_import_TransInfo_get_match_selected_manually(const GNCImportTransInfo *info)
Returns if the currently selected match was selected by the user.
GNCImportMatchInfo * gnc_import_TransInfo_get_selected_match(const GNCImportTransInfo *info)
Returns the currently selected match in this TransInfo.

◆ gnc_import_MatchInfo_get_probability()

gint gnc_import_MatchInfo_get_probability ( const GNCImportMatchInfo info)

Get the probability (confidence level) of this MatchInfo.

Parameters
infoCan be NULL, in which case the function returns 0

Definition at line 333 of file import-backend.cpp.

334 {
335  if (info)
336  return info->probability;
337  else
338  return 0;
339 }

◆ gnc_import_MatchInfo_get_split()

Split * gnc_import_MatchInfo_get_split ( const GNCImportMatchInfo info)

Get the split ('this-side split') of this MatchInfo.

Definition at line 326 of file import-backend.cpp.

327 {
328  g_assert (info);
329  return info->split;
330 }

◆ gnc_import_process_trans_item()

gboolean gnc_import_process_trans_item ( Account base_acc,
GNCImportTransInfo *  trans_info 
)

/brief – Processes one match according to its selected action.

This function is intended to be called when the importer dialog is finished.

It should be called once for each imported transaction and processes each ImportTransInfo according to its selected action: For GNCImport_ADD, the transaction is added etc. etc.

Each successful match is also stored in the match map of the given account, or if that argument is NULL, in the match map of each originating account.

Parameters
base_accThe account where each match should be stored. May be NULL, in which case each originating account will be used.
trans_infoThe ImportTransInfo item to process.
Returns
TRUE if the item has been processed.

Definition at line 888 of file import-backend.cpp.

890 {
891  g_assert (trans_info);
892  /*DEBUG("Iteration %d, action %d, split %s", i,
893  trans_info->action,
894  xaccTransGetDescription (gnc_import_TransInfo_get_trans
895  (trans_info)))*/
896  switch (gnc_import_TransInfo_get_action (trans_info))
897  {
898  case GNCImport_SKIP:
899  return false;
900  case GNCImport_ADD:
901  /* Transaction gets imported. */
902  if (!gnc_import_TransInfo_is_balanced(trans_info)
903  && gnc_import_TransInfo_get_destacc(trans_info))
904  {
905  /* Create the 'other' split. */
906  auto trans = gnc_import_TransInfo_get_trans (trans_info);
907  auto acct = gnc_import_TransInfo_get_destacc (trans_info);
908  auto split = xaccMallocSplit (gnc_account_get_book (acct));
909  xaccTransAppendSplit (trans, split);
910  xaccAccountInsertSplit (acct, split);
911  xaccSplitSetValue (split, trans_info->lsplit_value);
912  if (!gnc_numeric_zero_p (trans_info->lsplit_amount))
913  xaccSplitSetAmount (split, trans_info->lsplit_amount);
914  else
915  {
916  /* Bad! user asked to create a balancing split in an account with
917  * different currency/commodit than the transaction but didn't provide
918  * an exchange rate.
919  * Continue anyway pretenting split is in transaction currency. */
920  xaccSplitSetAmount (split, trans_info->lsplit_value);
921  PWARN("Missing exchange rate while adding transaction '%s', will assume rate of 1",
923  }
924  }
925 
927  /*Set reconcile date to today*/
929  gnc_time (nullptr));
930  /* Done editing. */
931  xaccTransCommitEdit(trans_info->trans);
932  xaccTransRecordPrice(trans_info->trans, PRICE_SOURCE_SPLIT_IMPORT);
933  return true;
934  case GNCImport_UPDATE:
935  {
936  auto selected_match = gnc_import_TransInfo_get_selected_match(trans_info);
937 
938  /* If there is no selection, ignore this transaction. */
939  if (!selected_match)
940  {
941  PWARN("No matching transaction to be cleared was chosen. Imported transaction will be ignored.");
942  break;
943  }
944 
945  /* Transaction gets not imported but the matching one gets
946  updated and reconciled. */
947  if (!gnc_import_MatchInfo_get_split(selected_match))
948  PERR("The split I am trying to update and reconcile is nullptr, shouldn't happen!");
949  else
950  {
951  /* Update and reconcile the matching transaction */
952  /*DEBUG("BeginEdit selected_match")*/
953  xaccTransBeginEdit(selected_match->trans);
954 
955  auto fsplit = gnc_import_TransInfo_get_fsplit(trans_info);
956  xaccTransSetDatePostedSecsNormalized(selected_match->trans,
958 
959  auto match_split_amount = xaccSplitGetAmount(selected_match->split);
960  xaccSplitSetAmount(selected_match->split, xaccSplitGetAmount(fsplit));
961  xaccSplitSetValue(selected_match->split, xaccSplitGetValue(fsplit));
962 
963  auto imbalance_value = gnc_import_TransInfo_get_dest_value(trans_info);
964  auto other_split = xaccSplitGetOtherSplit(selected_match->split);
965  if (!gnc_numeric_zero_p(imbalance_value) && other_split)
966  {
967  if (xaccSplitGetReconcile(other_split) == NREC)
968  {
969  xaccSplitSetValue(other_split, imbalance_value);
970  auto new_amt = gnc_import_TransInfo_get_dest_value(trans_info);
971  if (gnc_numeric_zero_p(new_amt))
972  {
973  auto other_split_amount = xaccSplitGetAmount(other_split);
974  auto price = gnc_numeric_div(match_split_amount, other_split_amount,
977 
978  new_amt = gnc_numeric_mul(xaccSplitGetAmount(fsplit), price,
981  }
982  xaccSplitSetAmount(other_split, new_amt);
983  }
984  else
985  {
986  /* else GC will automatically insert a split to equity
987  to balance the transaction */
988  PWARN("Updated transaction '%s', but not other split.",
989  xaccTransGetDescription(selected_match->trans));
990  }
991  }
992 
993  auto fs_memo = xaccSplitGetMemo (trans_info->first_split);
994  if (fs_memo && *fs_memo)
995  xaccSplitSetMemo(selected_match->split, fs_memo);
996 
997  update_desc_and_notes(trans_info);
998 
999  /*DEBUG("CommitEdit selected_match")*/
1000  xaccTransCommitEdit(selected_match->trans);
1001 
1002  process_reconcile (base_acc, trans_info, selected_match);
1003  }
1004  }
1005  return true;
1006  case GNCImport_CLEAR:
1007  {
1008  auto selected_match = gnc_import_TransInfo_get_selected_match (trans_info);
1009 
1010  /* If there is no selection, ignore this transaction. */
1011  if (!selected_match)
1012  {
1013  PWARN("No matching translaction to be cleared was chosen. Imported transaction will be ignored.");
1014  break;
1015  }
1016 
1017  /* Transaction gets not imported but the matching one gets
1018  reconciled. */
1019  if (!gnc_import_MatchInfo_get_split (selected_match))
1020  PERR("The split I am trying to reconcile is nullptr, shouldn't happen!");
1021  else
1022  {
1023  /* Reconcile the matching transaction */
1024  process_reconcile(base_acc, trans_info, selected_match);
1025  }
1026  }
1027  return true;
1028  default:
1029  DEBUG("Invalid GNCImportAction for this imported transaction.");
1030  break;
1031  }
1032  /*DEBUG("End");*/
1033  return false;
1034 }
void xaccSplitSetValue(Split *split, gnc_numeric val)
The xaccSplitSetValue() method sets the value of this split in the transaction&#39;s commodity.
Definition: gmock-Split.cpp:92
#define xaccTransAppendSplit(t, s)
Add a split to the transaction.
Definition: Transaction.h:381
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
This function sets the posted date of the transaction, specified by a time64 (see ctime(3))...
gnc_numeric gnc_import_TransInfo_get_dest_value(const GNCImportTransInfo *info)
Returns the destination split value for this TransInfo.
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
char xaccSplitGetReconcile(const Split *split)
Returns the value of the reconcile flag.
Split * gnc_import_TransInfo_get_fsplit(const GNCImportTransInfo *info)
Returns the first split of the transaction of this TransInfo.
Transaction * gnc_import_TransInfo_get_trans(const GNCImportTransInfo *info)
Returns the transaction of this TransInfo.
void xaccTransRecordPrice(Transaction *trans, PriceSource source)
The xaccTransRecordPrice() method iterates through the splits and and record the non-currency equival...
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
void xaccSplitSetReconcile(Split *split, char recn)
Set the reconcile flag.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
GNCImportAction gnc_import_TransInfo_get_action(const GNCImportTransInfo *info)
Returns the currently selected action for this TransInfo.
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
Split * gnc_import_MatchInfo_get_split(const GNCImportMatchInfo *info)
Get the split (&#39;this-side split&#39;) of this MatchInfo.
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account&#39;s commodity that the split should have...
Definition: gmock-Split.cpp:77
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Multiply a times b, returning the product.
void xaccSplitSetMemo(Split *split, const char *memo)
The memo is an arbitrary string associated with a split.
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
gnc_numeric gnc_numeric_div(gnc_numeric x, gnc_numeric y, gint64 denom, gint how)
Division.
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
#define CREC
The Split has been cleared.
Definition: Split.h:73
Split * xaccMallocSplit(QofBook *book)
Constructor.
Definition: gmock-Split.cpp:37
void xaccSplitSetDateReconciledSecs(Split *split, time64 secs)
Set the date on which this split was reconciled by specifying the time as time64. ...
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction&#39;s commodity.
Definition: gmock-Split.cpp:84
#define xaccAccountInsertSplit(acc, s)
The xaccAccountInsertSplit() method will insert the indicated split into the indicated account...
Definition: Account.h:1052
Split * xaccSplitGetOtherSplit(const Split *split)
The xaccSplitGetOtherSplit() is a convenience routine that returns the other of a pair of splits...
Account * gnc_import_TransInfo_get_destacc(const GNCImportTransInfo *info)
Returns the &#39;other account&#39; of this transaction.
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
Definition: gnc-numeric.h:165
time64 gnc_time(time64 *tbuf)
get the current time
Definition: gnc-date.cpp:262
const char * xaccSplitGetMemo(const Split *split)
Returns the memo string.
Definition: gmock-Split.cpp:99
GNCImportMatchInfo * gnc_import_TransInfo_get_selected_match(const GNCImportTransInfo *info)
Returns the currently selected match in this TransInfo.
#define GNC_DENOM_AUTO
Values that can be passed as the &#39;denom&#39; argument.
Definition: gnc-numeric.h:245
gboolean gnc_import_TransInfo_is_balanced(const GNCImportTransInfo *info)
Returns if the transaction stored in the TransInfo is currently balanced.
#define NREC
not reconciled or cleared
Definition: Split.h:76
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account&#39;s commodity.
Definition: gmock-Split.cpp:69

◆ gnc_import_select_account()

Account * gnc_import_select_account ( GtkWidget *  parent,
const gchar *  account_online_id_value,
gboolean  prompt_on_no_match,
const gchar *  account_human_description,
const gnc_commodity *  new_account_default_commodity,
GNCAccountType  new_account_default_type,
Account default_selection,
gboolean *  ok_pressed 
)

Must be called with a string containing a unique identifier for the account.

If an account with a matching online_id is found, the function immediately returns with a pointer to that account. Otherwise, the user is prompted to select a GnuCash account or create a new one (in both cases, the unique identifier is written to the account, so the user won't be prompted again). If the user refuses to select or create an account, NULL is returned.

Parameters
parentThe parent widget. Can be NULL.
account_online_id_valueThe string containing your unique account_id coming from some string of your module. This is the normal mode of operation. Can be NULL.

If account_online_id_value==NULL, you basically end up with an account selector that allows you to select an account whose GncGUID will be remembered elsewhere. You would fill account_human_description to tell the user what he is looking for. In this mode, the online_id field of the found account will not be touched. To use this mode, prompt_on_no_match must NOT be set to 0.

Parameters
account_human_descriptionA human-readable description of the account. Can be NULL. If it is not NULL, it will be shown before the id in the account matching dialog. It will also be used as the default account name if a new account is created.
new_account_default_commodityDefault commodity of the new account. Can be NULL. If not NULL, it will be the account's commodity if a new account is created. Also, if not NULL, the function will also warn the user if the found or created account's commodity doesn't match.
new_account_default_typeDefault account type of a new account. Can be NULL. If not ACCT_TYPE_NONE, it will be the account's type if a new account is created. If not ACCT_TYPE_NONE, the function will also warn the user if the found or created account's commodity doesn't match.
prompt_on_no_matchOnly active if no account with the account_online_id_value could be found in gnucash, or if online-id was NULL. In that case, if prompt_on_no_match is TRUE (nonzero), the user will be asked to create a new account. If prompt_on_no_match is FALSE (zero), this function will simply return NULL but will neither select nor create any account.
default_selectionIf not NULL, that account will be pre-selected by default.
ok_pressedA pointer to gboolean. If non-NULL, whether or not the picker dialog was closed by the user pressing ok will be stored in the parameter. If no dialog was created by the gnc_import_select_account() call, TRUE is always returned.
Returns
A pointer to the found or created Account, or NULL if no account was found or created.

Definition at line 339 of file import-account-matcher.cpp.

347 {
348 #define ACCOUNT_DESCRIPTION_MAX_SIZE 255
349  AccountPickerDialog * picker;
350  gint response;
351  Account * retval = NULL;
352  const gchar *retval_name = NULL;
353  GtkBuilder *builder;
354  GtkTreeSelection *selection;
355  GtkWidget * online_id_label;
356  gchar account_description_text[ACCOUNT_DESCRIPTION_MAX_SIZE + 1] = "";
357  gboolean ok_pressed_retval = FALSE;
358 
359  ENTER("Default commodity received: %s", gnc_commodity_get_fullname( new_account_default_commodity));
360  DEBUG("Default account type received: %s", xaccAccountGetTypeStr( new_account_default_type));
361  picker = g_new0(AccountPickerDialog, 1);
362 
363  picker->account_human_description = account_human_description;
364  picker->new_account_default_commodity = new_account_default_commodity;
365  picker->new_account_default_type = new_account_default_type;
366 
367  /*DEBUG("Looking for account with online_id: \"%s\"", account_online_id_value);*/
368  if (account_online_id_value)
369  {
370  AccountOnlineMatch match = {NULL, 0, account_online_id_value};
371  retval = static_cast<Account*>(gnc_account_foreach_descendant_until (gnc_get_current_root_account (),
372  test_acct_online_id_match,
373  (void*)&match));
374  if (!retval && match.count == 1 &&
375  new_account_default_type == ACCT_TYPE_NONE)
376  retval = match.partial_match;
377  }
378  if (!retval && prompt_on_no_match)
379  {
380  /* load the interface */
381  builder = gtk_builder_new();
382  gnc_builder_add_from_file (builder, "dialog-import.glade", "account_new_icon");
383  gnc_builder_add_from_file (builder, "dialog-import.glade", "account_picker_dialog");
384  /* connect the signals in the interface */
385  if (builder == NULL)
386  {
387  PERR("Error opening the glade builder interface");
388  }
389  picker->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker_dialog"));
390  picker->whbox = GTK_WIDGET(gtk_builder_get_object (builder, "warning_hbox"));
391  picker->warning = GTK_WIDGET(gtk_builder_get_object (builder, "warning_label"));
392  picker->ok_button = GTK_WIDGET(gtk_builder_get_object (builder, "okbutton"));
393 
394  // Set the name for this dialog so it can be easily manipulated with css
395  gtk_widget_set_name (GTK_WIDGET(picker->dialog), "gnc-id-import-account-picker");
396  gnc_widget_style_context_add_class (GTK_WIDGET(picker->dialog), "gnc-class-imports");
397 
398  if (parent)
399  gtk_window_set_transient_for (GTK_WINDOW (picker->dialog),
400  GTK_WINDOW (parent));
401 
402  gnc_restore_window_size (GNC_PREFS_GROUP,
403  GTK_WINDOW(picker->dialog), GTK_WINDOW (parent));
404 
405  picker->account_tree_sw = GTK_WIDGET(gtk_builder_get_object (builder, "account_tree_sw"));
406  online_id_label = GTK_WIDGET(gtk_builder_get_object (builder, "online_id_label"));
407 
408  //printf("gnc_import_select_account(): Fin get widget\n");
409 
410  if (account_human_description != NULL)
411  {
412  strncat(account_description_text, account_human_description,
413  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
414  strncat(account_description_text, "\n",
415  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
416  }
417  if (account_online_id_value != NULL)
418  {
419  strncat(account_description_text, _("(Full account ID: "),
420  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
421  strncat(account_description_text, account_online_id_value,
422  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
423  strncat(account_description_text, ")",
424  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
425  }
426  gtk_label_set_text((GtkLabel*)online_id_label, account_description_text);
427  build_acct_tree(picker);
428  gtk_window_set_modal(GTK_WINDOW(picker->dialog), TRUE);
429  g_signal_connect(picker->account_tree, "row-activated",
430  G_CALLBACK(account_tree_row_activated_cb), picker);
431 
432  /* Connect key press event so we can expand the tree when the user starts typing, allowing
433  * any subaccount to match */
434  g_signal_connect (picker->account_tree, "key-press-event", G_CALLBACK (account_tree_key_press_cb), picker->account_tree);
435 
436  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(picker->account_tree));
437  g_signal_connect(selection, "changed",
438  G_CALLBACK(account_tree_row_changed_cb), picker);
439 
440  gnc_tree_view_account_set_selected_account(picker->account_tree, default_selection);
441 
442  do
443  {
444  response = gtk_dialog_run(GTK_DIALOG(picker->dialog));
445  switch (response)
446  {
447  case GNC_RESPONSE_NEW:
448  gnc_import_add_account(NULL, picker);
449  response = GTK_RESPONSE_OK;
450  /* no break */
451 
452  case GTK_RESPONSE_OK:
453  retval = gnc_tree_view_account_get_selected_account(picker->account_tree);
454  if (!retval)
455  {
456  response = GNC_RESPONSE_NEW;
457  break;
458  }
459  retval_name = xaccAccountGetName(retval);
460  DEBUG("Selected account %p, %s", retval, retval_name ? retval_name : "(null)");
461 
462  /* See if the selected account is a placeholder. */
463  if (retval && xaccAccountGetPlaceholder (retval))
464  {
465  show_placeholder_warning (picker, retval_name);
466  response = GNC_RESPONSE_NEW;
467  break;
468  }
469 
470  if (account_online_id_value)
471  {
472  gnc_import_set_acc_online_id(retval, account_online_id_value);
473  }
474  ok_pressed_retval = TRUE;
475  break;
476 
477  default:
478  ok_pressed_retval = FALSE;
479  break;
480  }
481  }
482  while (response == GNC_RESPONSE_NEW);
483 
484  g_object_unref(G_OBJECT(builder));
485  gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(picker->dialog));
486  gtk_widget_destroy(picker->dialog);
487  }
488  else
489  {
490  retval_name = retval ? xaccAccountGetName(retval) : NULL;
491  ok_pressed_retval = TRUE; /* There was no dialog involved, so the computer "pressed" ok */
492  }
493  /*FIXME: DEBUG("WRITEME: gnc_import_select_account() Here we should check if account type is compatible, currency matches, etc.\n"); */
494  g_free(picker);
495  /*DEBUG("Return value: %p%s%s%s",retval,", account name:",xaccAccountGetName(retval),"\n");*/
496  if (ok_pressed != NULL)
497  {
498  *ok_pressed = ok_pressed_retval;
499  }
500  LEAVE("Selected account %p, %s", retval, retval_name ? retval_name : "(null)");
501  return retval;
502 }
STRUCTS.
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
gpointer gnc_account_foreach_descendant_until(const Account *acc, AccountCb2 thunk, gpointer user_data)
This method will traverse all children of this accounts and their descendants, calling &#39;func&#39; on each...
Definition: Account.cpp:3218
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
Retrieve the full name for the specified commodity.
void gnc_tree_view_account_set_selected_account(GncTreeViewAccount *view, Account *account)
This function selects an account in the account tree view.
gboolean xaccAccountGetPlaceholder(const Account *acc)
Get the "placeholder" flag for an account.
Definition: Account.cpp:4078
Account * gnc_tree_view_account_get_selected_account(GncTreeViewAccount *view)
This function returns the account associated with the selected item in the account tree view...
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
const char * xaccAccountGetName(const Account *acc)
Get the account&#39;s name.
Definition: Account.cpp:3263
const char * xaccAccountGetTypeStr(GNCAccountType type)
The xaccAccountGetTypeStr() routine returns a string suitable for use in the GUI/Interface.
Definition: Account.cpp:4316
Not a type.
Definition: Account.h:105

◆ gnc_import_select_commodity()

gnc_commodity * gnc_import_select_commodity ( const char *  cusip,
gboolean  ask_on_unknown,
const char *  default_fullname,
const char *  default_mnemonic 
)

Must be called with a string containing a unique identifier for the commodity.

If an commodity with a matching cusip is found, the function immediately returns with a pointer to that commodity. Otherwise, the user may be prompted to select a GnuCash commodity or create a new one (in both cases, the cusip is written to the commodity's cusip field, overwriting anything that was there before.

Parameters
cusipThe string containing the code for which you want a matching commodity. A CUISP code or similar UNIQUE code. The stock ticker is NOT appropriate, unless you have no other option. Must be non-NULL.
ask_on_unknownIf the cusip value is unknown and this parameter is false (zero), the function returns NULL. Otherwise the user will be asked to select an existing or create a new commodity.
default_fullnameA human-readable description of the commodity, such as the stock name. Can be NULL. If it is not NULL, it will be shown to the user when selecting a commodity. It will also be used as the default if a new commodity is created.
default_mnemonicUsually the stock ticker or similar. Can be NULL. If it is not NULL, it will be shown to the user when selecting a commodity. It will also be used as the default if a new commodity is created.
Returns
A pointer to the found or created commodity, or NULL if no commodity was found or created.

Definition at line 53 of file import-commodity-matcher.cpp.

57 {
58  const gnc_commodity_table * commodity_table = gnc_get_current_commodities ();
59  gnc_commodity * retval = NULL;
60  DEBUG("Default fullname received: %s", default_fullname);
61  DEBUG("Default mnemonic received: %s", default_mnemonic);
62 
63  g_return_val_if_fail(cusip, NULL);
64  DEBUG("Looking for commodity with exchange_code: %s", cusip);
65 
66  g_assert(commodity_table);
67  GList *namespace_list = gnc_commodity_table_get_namespaces(commodity_table);
68 
69  for (GList *n = namespace_list; !retval && n; n = g_list_next (n))
70  {
71  auto ns = static_cast<const char*>(n->data);
72  DEBUG("Looking at namespace %s", ns);
73  GList *comm_list = gnc_commodity_table_get_commodities (commodity_table, ns);
74  for (GList *m = comm_list; !retval && m; m = g_list_next (m))
75  {
76  auto com = static_cast<gnc_commodity*>(m->data);
77  DEBUG("Looking at commodity %s", gnc_commodity_get_fullname (com));
78  if (!g_strcmp0 (gnc_commodity_get_cusip (com), cusip))
79  {
80  retval = com;
81  DEBUG("Commodity %s matches.", gnc_commodity_get_fullname (com));
82  }
83  }
84  g_list_free (comm_list);
85  }
86 
87  g_list_free(namespace_list);
88 
89  if (retval == NULL && ask_on_unknown != 0)
90  {
91  const gchar *message =
92  _("Please select a commodity to match the following exchange "
93  "specific code. Please note that the exchange code of the "
94  "commodity you select will be overwritten.");
96  NULL,
98  message,
99  cusip,
100  default_fullname,
101  default_mnemonic);
102 
103  }
104  /* There seems to be a problem here - if the matched commodity does not
105  have a cusip defined (gnc_commodity_get_cusip returns NULL) then
106  it does not get overwritten - which is not consistent with the
107  message - so Im adding it to do this. Looks like this is all
108  that was needed to fix the cash value used as stock units problem
109  for pre-defined commodities which didn't have the cusip defined! */
110  if (retval != NULL &&
111  gnc_commodity_get_cusip(retval) != NULL &&
112  cusip != NULL &&
113  (strncmp(gnc_commodity_get_cusip(retval), cusip, strlen(cusip)) != 0))
114  {
115  gnc_commodity_set_cusip(retval, cusip);
116  }
117  else if (gnc_commodity_get_cusip(retval) == NULL && cusip != NULL)
118  {
119  gnc_commodity_set_cusip(retval, cusip);
120  }
121  return retval;
122 }
const char * gnc_commodity_get_cusip(const gnc_commodity *cm)
Retrieve the &#39;exchange code&#39; for the specified commodity.
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
Dialog box should allow selection of anything.
GList * gnc_commodity_table_get_namespaces(const gnc_commodity_table *table)
Return a list of all namespaces in the commodity table.
void gnc_commodity_set_cusip(gnc_commodity *cm, const char *cusip)
Set the &#39;exchange code&#39; for the specified commodity.
gnc_commodity * gnc_ui_select_commodity_modal_full(gnc_commodity *orig_sel, GtkWidget *parent, dialog_commodity_mode mode, const char *user_message, const char *cusip, const char *fullname, const char *mnemonic)
Ask the user to select a commodity from the existing set of commodities.
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
Retrieve the full name for the specified commodity.
CommodityList * gnc_commodity_table_get_commodities(const gnc_commodity_table *table, const char *name_space)
Return a list of all commodities in the commodity table that are in the given namespace.

◆ gnc_import_Settings_get_fuzzy_amount()

double gnc_import_Settings_get_fuzzy_amount ( GNCImportSettings *  settings)

Return the allowed amount range for fuzzy amount matching.

Returns
The allowed amount range for fuzzy amount matching, in the users default commodity.

Definition at line 122 of file import-settings.cpp.

123 {
124  g_assert (settings);
125  return settings->fuzzy_amount;
126 }

◆ gnc_import_Settings_get_match_date_hardlimit()

gint gnc_import_Settings_get_match_date_hardlimit ( const GNCImportSettings *  settings)

Returns the hard-limiting number of days that a matching split may differ.

Definition at line 188 of file import-settings.cpp.

189 {
190  g_assert(s);
191  return s->match_date_hardlimit;
192 }

◆ gnc_import_Settings_set_match_date_hardlimit()

void gnc_import_Settings_set_match_date_hardlimit ( GNCImportSettings *  settings,
gint  match_date_hardlimit 
)
Parameters
match_date_hardlimitThe number of days that a matching split may differ from the given transaction before it is discarded immediately. In other words, any split that is more distant from the given transaction than this match_date_hardlimit days will be ignored altogether. For use cases without paper checks (e.g. HBCI), values like 14 (days) might be appropriate, whereas for use cases with paper checks (e.g. OFX, QIF), values like 42 (days) seem more appropriate.

Definition at line 182 of file import-settings.cpp.

183 {
184  g_assert(s);
185  s->match_date_hardlimit = m;
186 }

◆ gnc_import_TransInfo_get_action()

GNCImportAction gnc_import_TransInfo_get_action ( const GNCImportTransInfo *  info)

Returns the currently selected action for this TransInfo.

Definition at line 193 of file import-backend.cpp.

194 {
195  g_assert (info);
196  return info->action;
197 }

◆ gnc_import_TransInfo_get_dest_amount()

gnc_numeric gnc_import_TransInfo_get_dest_amount ( const GNCImportTransInfo *  info)

Returns the destination split amount for this TransInfo.

Definition at line 278 of file import-backend.cpp.

279 {
280  g_assert (info);
281  return info->lsplit_amount;
282 }

◆ gnc_import_TransInfo_get_dest_value()

gnc_numeric gnc_import_TransInfo_get_dest_value ( const GNCImportTransInfo *  info)

Returns the destination split value for this TransInfo.

Definition at line 285 of file import-backend.cpp.

286 {
287  g_assert (info);
288  return info->lsplit_value;
289 }

◆ gnc_import_TransInfo_get_destacc()

Account * gnc_import_TransInfo_get_destacc ( const GNCImportTransInfo *  info)

Returns the 'other account' of this transaction.

May return NULL.

Definition at line 212 of file import-backend.cpp.

213 {
214  g_assert (info);
215  return info->dest_acc;
216 }

◆ gnc_import_TransInfo_get_destacc_selected_manually()

gboolean gnc_import_TransInfo_get_destacc_selected_manually ( const GNCImportTransInfo *  info)

Returns if the currently selected destination account for auto-matching was selected by the user.

Definition at line 233 of file import-backend.cpp.

234 {
235  g_assert (info);
236  return info->dest_acc_selected_manually;
237 }

◆ gnc_import_TransInfo_get_fsplit()

Split * gnc_import_TransInfo_get_fsplit ( const GNCImportTransInfo *  info)

Returns the first split of the transaction of this TransInfo.

Definition at line 162 of file import-backend.cpp.

163 {
164  g_assert (info);
165  return info->first_split;
166 }

◆ gnc_import_TransInfo_get_match_list()

GList * gnc_import_TransInfo_get_match_list ( const GNCImportTransInfo *  info)

Returns the stored list of possible matches.

Definition at line 127 of file import-backend.cpp.

128 {
129  g_assert (info);
130  return info->match_list;
131 }

◆ gnc_import_TransInfo_get_match_selected_manually()

gboolean gnc_import_TransInfo_get_match_selected_manually ( const GNCImportTransInfo *  info)

Returns if the currently selected match was selected by the user.

Definition at line 186 of file import-backend.cpp.

187 {
188  g_assert (info);
189  return info->selected_match_info.selected_manually;
190 }

◆ gnc_import_TransInfo_get_price()

gnc_numeric gnc_import_TransInfo_get_price ( const GNCImportTransInfo *  info)

Returns the exchange rate for this TransInfo.

Definition at line 255 of file import-backend.cpp.

256 {
257  g_assert (info);
258  return info->lsplit_price;
259 }

◆ gnc_import_TransInfo_get_ref_id()

guint32 gnc_import_TransInfo_get_ref_id ( const GNCImportTransInfo *  info)

Returns the reference id for this TransInfo.

Definition at line 240 of file import-backend.cpp.

241 {
242  g_assert (info);
243  return info->ref_id;
244 }

◆ gnc_import_TransInfo_get_selected_match()

GNCImportMatchInfo * gnc_import_TransInfo_get_selected_match ( const GNCImportTransInfo *  info)

Returns the currently selected match in this TransInfo.

Definition at line 169 of file import-backend.cpp.

170 {
171  g_assert (info);
172  return info->selected_match_info.selected_match;
173 }

◆ gnc_import_TransInfo_get_trans()

Transaction * gnc_import_TransInfo_get_trans ( const GNCImportTransInfo *  info)

Returns the transaction of this TransInfo.

Definition at line 148 of file import-backend.cpp.

149 {
150  g_assert (info);
151  return info->trans;
152 }

◆ gnc_import_TransInfo_init_matches()

void gnc_import_TransInfo_init_matches ( GNCImportTransInfo *  trans_info,
GNCImportSettings *  settings 
)

Iterates through all splits of trans_info's originating account match list.

Iterates through all splits of the originating account of trans_info.

Sorts the resulting list and sets the selected_match and action fields in the trans_info.

Sorts the resulting list and sets the selected_match and action fields in the trans_info.

Parameters
trans_infoThe TransInfo for which the matches should be found, sorted, and selected.
settingsThe structure that holds all the user preferences.

Definition at line 1166 of file import-backend.cpp.

1168 {
1169  g_assert (trans_info);
1170 
1171  if (trans_info->match_list)
1172  {
1173  DEBUG("Number of matches %d", g_list_length(trans_info->match_list));
1174 
1175  trans_info->match_list = g_list_sort(trans_info->match_list,
1176  compare_probability);
1177  auto best_match = static_cast<GNCImportMatchInfo*>(g_list_nth_data(trans_info->match_list, 0));
1178  gnc_import_TransInfo_set_selected_match_info (trans_info, best_match, false);
1179  if (best_match &&
1180  best_match->probability >= gnc_import_Settings_get_clear_threshold(settings))
1181  {
1183  best_match->update_proposed)
1184  trans_info->action = GNCImport_UPDATE;
1185  else
1186  trans_info->action = GNCImport_CLEAR;
1187  }
1188  else if (!best_match ||
1189  best_match->probability <= gnc_import_Settings_get_add_threshold(settings))
1190  trans_info->action = GNCImport_ADD;
1192  trans_info->action = GNCImport_SKIP;
1194  trans_info->action = GNCImport_UPDATE;
1195  else
1196  trans_info->action = GNCImport_ADD;
1197  }
1198  else
1199  trans_info->action = GNCImport_ADD;
1200 
1201 
1202  trans_info->previous_action = trans_info->action;
1203 }
gint gnc_import_Settings_get_clear_threshold(GNCImportSettings *settings)
Return the selected threshold.
void gnc_import_TransInfo_set_selected_match_info(GNCImportTransInfo *info, GNCImportMatchInfo *match, gboolean selected_manually)
Sets the currently selected match in this TransInfo.
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
gboolean gnc_import_Settings_get_action_update_enabled(GNCImportSettings *settings)
Return the selected action is enable state.
gboolean gnc_import_Settings_get_action_skip_enabled(GNCImportSettings *settings)
Return the selected action is enable state.
gint gnc_import_Settings_get_add_threshold(GNCImportSettings *settings)
Return the selected threshold.

◆ gnc_import_TransInfo_is_balanced()

gboolean gnc_import_TransInfo_is_balanced ( const GNCImportTransInfo *  info)

Returns if the transaction stored in the TransInfo is currently balanced.

Definition at line 155 of file import-backend.cpp.

156 {
157  g_assert (info);
159 }
Transaction * gnc_import_TransInfo_get_trans(const GNCImportTransInfo *info)
Returns the transaction of this TransInfo.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
gnc_numeric xaccTransGetImbalanceValue(const Transaction *trans)
The xaccTransGetImbalanceValue() method returns the total value of the transaction.

◆ gnc_import_TransInfo_new()

GNCImportTransInfo * gnc_import_TransInfo_new ( Transaction *  trans,
Account base_acc 
)

Create a new object of GNCImportTransInfo here.

Allocates a new TransInfo object, with the Transaction 'trans' already stored in there.

Also, this already checks the account's match map for automated destination account matching. The given account may be NULL, in which case the match map of the originating account will be used.

Parameters
transThe transaction that this TransInfo should work with.
base_accAccount that will provide the match map to lookup a destination account. This may be NULL, in which case the match map of the originating account will be used.

Definition at line 1131 of file import-backend.cpp.

1132 {
1133  g_assert (trans);
1134 
1135  auto t_info = g_new0(GNCImportTransInfo, 1);
1136 
1137  t_info->trans = trans;
1138  /* Only use first split, the source split */
1139  auto split = xaccTransGetSplit(trans, 0);
1140  g_assert(split);
1141  t_info->first_split = split;
1142 
1143  /* Try to find a previously selected destination account
1144  string match for the ADD action */
1146  matchmap_find_destination (base_acc, t_info),
1147  false);
1148 
1149  return t_info;
1150 }
Split * xaccTransGetSplit(const Transaction *trans, int i)
Return a pointer to the indexed split in this transaction&#39;s split list.
void gnc_import_TransInfo_set_destacc(GNCImportTransInfo *info, Account *acc, gboolean selected_manually)
Set the &#39;other account&#39; of this transaction (used for auto-balance if needed).

◆ gnc_import_TransInfo_set_action()

void gnc_import_TransInfo_set_action ( GNCImportTransInfo *  info,
GNCImportAction  action 
)

Set the action for this TransInfo.

Also sets the previous action.

Definition at line 200 of file import-backend.cpp.

202 {
203  g_assert (info);
204  if (action != info->action)
205  {
206  info->previous_action = info->action;
207  info->action = action;
208  }
209 }

◆ gnc_import_TransInfo_set_append_text()

void gnc_import_TransInfo_set_append_text ( GNCImportTransInfo *  info,
gboolean  append_text 
)

Set the append_text for this TransInfo.

Definition at line 317 of file import-backend.cpp.

319 {
320  g_assert (info);
321  info->append_text = append_text;
322 }

◆ gnc_import_TransInfo_set_destacc()

void gnc_import_TransInfo_set_destacc ( GNCImportTransInfo *  info,
Account acc,
gboolean  selected_manually 
)

Set the 'other account' of this transaction (used for auto-balance if needed).

May be set to NULL.

Parameters
selected_manuallyTRUE or FALSE; Was this account set as a result of a selection by the user or by an algorithm?

Definition at line 217 of file import-backend.cpp.

220 {
221  g_assert (info);
222  info->dest_acc = acc;
223  info->dest_acc_selected_manually = selected_manually;
224 
225  /* Store the mapping to the other account in the MatchMap. */
226  if (selected_manually)
227  matchmap_store_destination (nullptr, info, false);
228 
229  trans_info_calculate_dest_amount (info);
230 }

◆ gnc_import_TransInfo_set_price()

void gnc_import_TransInfo_set_price ( GNCImportTransInfo *  info,
gnc_numeric  lprice 
)

Set the exchange rate for this TransInfo.

Definition at line 262 of file import-backend.cpp.

264 {
265  g_assert (info);
266  info->lsplit_price = lprice;
267  /* if a valid price is explicitly set, assume the user wants to
268  * use it to calculate balance split amount.
269  * Ensure this gets recalculated */
270  if (gnc_numeric_check (lprice) == 0)
271  {
272  info->lsplit_amount_selected_manually = false;
273  trans_info_calculate_dest_amount(info);
274  }
275 }
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
Check for error signal in value.

◆ gnc_import_TransInfo_set_ref_id()

void gnc_import_TransInfo_set_ref_id ( GNCImportTransInfo *  info,
guint32  ref_id 
)

Set the reference id for this TransInfo.

Definition at line 247 of file import-backend.cpp.

249 {
250  g_assert (info);
251  info->ref_id = ref_id;
252 }

◆ gnc_import_TransInfo_set_selected_match_info()

void gnc_import_TransInfo_set_selected_match_info ( GNCImportTransInfo *  info,
GNCImportMatchInfo match,
gboolean  selected_manually 
)

Sets the currently selected match in this TransInfo.

Parameters
selected_manuallyTRUE or FALSE; Was this match set as a result of a selection by the user or by an algorithm?

Definition at line 176 of file import-backend.cpp.

179 {
180  g_assert (info);
181  info->selected_match_info.selected_match = match;
182  info->selected_match_info.selected_manually = selected_manually;
183 }

◆ on_matcher_help_clicked()

void on_matcher_help_clicked ( GtkButton *  button,
gpointer  user_data 
)

This allows for the transaction help dialog to be started from the assistant button callback.

Parameters
button.The button widget clicked on in the call back.
user_data.A pointer to a structure.

Definition at line 630 of file import-main-matcher.cpp.

631 {
632  auto info = static_cast<GNCImportMainMatcher*>(user_data);
633 
634  GtkBuilder *builder = gtk_builder_new ();
635  gnc_builder_add_from_file (builder, "dialog-import.glade", "textbuffer2");
636  gnc_builder_add_from_file (builder, "dialog-import.glade", "textbuffer3");
637  gnc_builder_add_from_file (builder, "dialog-import.glade", "textbuffer4");
638  gnc_builder_add_from_file (builder, "dialog-import.glade", "textbuffer5");
639  gnc_builder_add_from_file (builder, "dialog-import.glade", "textbuffer1");
640  gnc_builder_add_from_file (builder, "dialog-import.glade", "matcher_help_dialog");
641 
642  const gchar *class_extension = NULL;
643  if (info->dark_theme == true)
644  class_extension = "-dark";
645 
646  gchar *int_required_class = g_strconcat (CSS_INT_REQUIRED_CLASS, class_extension, NULL);
647  gchar *int_prob_required_class = g_strconcat (CSS_INT_PROB_REQUIRED_CLASS, class_extension, NULL);
648  gchar *int_not_required_class = g_strconcat (CSS_INT_NOT_REQUIRED_CLASS, class_extension, NULL);
649 
650  GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder, "intervention_required_box"));
651  gnc_widget_style_context_add_class (GTK_WIDGET(box), int_required_class);
652 
653  box = GTK_WIDGET(gtk_builder_get_object (builder, "intervention_probably_required_box"));
654  gnc_widget_style_context_add_class (GTK_WIDGET(box), int_prob_required_class);
655 
656  box = GTK_WIDGET(gtk_builder_get_object (builder, "intervention_not_required_box"));
657  gnc_widget_style_context_add_class (GTK_WIDGET(box), int_not_required_class);
658 
659  GtkWidget *help_dialog = GTK_WIDGET(gtk_builder_get_object (builder, "matcher_help_dialog"));
660  gtk_window_set_transient_for (GTK_WINDOW(help_dialog), GTK_WINDOW(info->main_widget));
661 
662  // Set the name for this dialog so it can be easily manipulated with css
663  gtk_widget_set_name (GTK_WIDGET(help_dialog), "gnc-id-import-matcher-help");
664  gnc_widget_style_context_add_class (GTK_WIDGET(help_dialog), "gnc-class-imports");
665 
666  /* Connect the signals */
667  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, help_dialog);
668 
669  g_object_unref (G_OBJECT(builder));
670 
671  g_free (int_required_class);
672  g_free (int_prob_required_class);
673  g_free (int_not_required_class);
674 
675  gtk_widget_show (help_dialog);
676 }

◆ split_find_match()

void split_find_match ( GNCImportTransInfo *  trans_info,
Split *  split,
gint  display_threshold,
gint  date_threshold,
gint  date_not_threshold,
double  fuzzy_amount_difference 
)

The transaction matching heuristics are here.

Evaluates the match between trans_info and split using the provided parameters.

Parameters
trans_infoThe TransInfo for the imported transaction
splitThe register split that should be evaluated for a match.
display_thresholdMinimum match score to include split in the list of matches.
date_thresholdMaximum number of days a match considered likely.
date_not_thresholdMinimum number of days a match is considered unlikely.
fuzzy_amount_differenceMaximum amount difference to consider the match good.

Definition at line 579 of file import-backend.cpp.

585 {
586  gint prob = 0;
587 
588  auto new_trans = gnc_import_TransInfo_get_trans (trans_info);
589  auto new_trans_fsplit = gnc_import_TransInfo_get_fsplit (trans_info);
590 
591  /* Matching heuristics */
592 
593  /* Amount heuristics */
594  auto downloaded_split_amount =
595  gnc_numeric_to_double (xaccSplitGetAmount(new_trans_fsplit));
596  DEBUG(" downloaded_split_amount=%f", downloaded_split_amount);
597  auto match_split_amount = gnc_numeric_to_double(xaccSplitGetAmount(split));
598  DEBUG(" match_split_amount=%f", match_split_amount);
599  if (fabs(downloaded_split_amount - match_split_amount) < 1e-6)
600  /* bug#347791: Double type shouldn't be compared for exact
601  equality, so we're using fabs() instead. */
602  /*if (gnc_numeric_equal(xaccSplitGetAmount
603  (new_trans_fsplit),
604  xaccSplitGetAmount(split)))
605  -- gnc_numeric_equal is an expensive function call */
606  {
607  prob = prob + 3;
608  DEBUG("heuristics: probability + 3 (amount)");
609  }
610  else if (fabs (downloaded_split_amount - match_split_amount) <=
611  fuzzy_amount_difference)
612  {
613  /* ATM fees are sometimes added directly in the transaction.
614  So you withdraw 100$ and get charged 101,25$ in the same
615  transaction */
616  prob = prob + 2;
617  DEBUG("heuristics: probability + 2 (amount)");
618  }
619  else
620  {
621  /* If a transaction's amount doesn't match within the
622  threshold, it's very unlikely to be the same transaction
623  so we give it an extra -5 penalty */
624  prob = prob - 5;
625  DEBUG("heuristics: probability - 1 (amount)");
626  }
627 
628  /* Date heuristics */
629  auto match_time = xaccTransGetDate (xaccSplitGetParent (split));
630  auto download_time = xaccTransGetDate (new_trans);
631  auto datediff_day = llabs(match_time - download_time) / 86400;
632  /* Sorry, there are not really functions around at all that
633  provide for less hacky calculation of days of date
634  differences. Whatever. On the other hand, the difference
635  calculation itself will work regardless of month/year
636  turnarounds. */
637  auto download_time_str = qof_print_date(download_time);
638  auto match_time_str = qof_print_date(match_time);
639  DEBUG("Date download: %s vs match: %s", download_time_str, match_time_str);
640  g_free (download_time_str);
641  g_free (match_time_str);
642  DEBUG("diff day %lld", datediff_day);
643  if (datediff_day == 0)
644  {
645  prob = prob + 3;
646  DEBUG("heuristics: probability + 3 (date)");
647  }
648  else if (datediff_day <= date_threshold)
649  {
650  prob = prob + 2;
651  DEBUG("heuristics: probability + 2 (date)");
652  }
653  else if (datediff_day > date_not_threshold)
654  {
655  /* Extra penalty if that split lies awfully far away from
656  the given one. */
657  prob = prob - 5;
658  DEBUG("heuristics: probability - 5 (date)");
659  /* Changed 2005-02-21: Revert the hard-limiting behaviour
660  back to the previous large penalty. (Changed 2004-11-27:
661  The penalty is so high that we can forget about this
662  split anyway and skip the rest of the tests.) */
663  }
664 
665  /* Check if date and amount are identical */
666  auto update_proposed = (prob < 6);
667 
668  /* Check number heuristics */
669  auto new_trans_str = gnc_get_num_action(new_trans, new_trans_fsplit);
670  auto split_str = gnc_get_num_action (xaccSplitGetParent (split), split);
671  DEBUG("number download: '%s' to match: '%s'", new_trans_str, split_str);
672  if (new_trans_str && *new_trans_str && split_str && *split_str)
673  {
674  char *endptr;
675  auto conversion_ok = true;
676 
677  /* To distinguish success/failure after strtol call */
678  errno = 0;
679  auto new_trans_number = strtol(new_trans_str, &endptr, 10);
680  /* Possible addressed problems: over/underflow, only non
681  numbers on string and string empty */
682  conversion_ok = !(errno || endptr == new_trans_str);
683 
684  errno = 0;
685  auto split_number = strtol(split_str, &endptr, 10);
686  conversion_ok = !(errno || endptr == split_str);
687 
688  if ( (conversion_ok && (split_number == new_trans_number)) ||
689  (g_strcmp0(new_trans_str, split_str) == 0) )
690  {
691  /* An exact match of the Check number gives a +4 */
692  prob += 4;
693  DEBUG("heuristics: probability + 4 (Check number)");
694  }
695  else if (strlen(new_trans_str) > 0 && strlen(split_str) > 0)
696  {
697  /* If both number are not empty yet do not match, add a
698  little extra penalty */
699  prob -= 2;
700  }
701  }
702 
703  /* Memo heuristics */
704  auto memo = xaccSplitGetMemo(new_trans_fsplit);
705  auto match_memo = xaccSplitGetMemo(split);
706  if (memo && *memo && match_memo && *match_memo)
707  {
708  DEBUG("memo download: '%s' to match: '%s'", memo, match_memo);
709  if (safe_strcasecmp(memo, match_memo) == 0)
710  {
711  /* An exact match of memo gives a +2 */
712  prob = prob + 2;
713  DEBUG("heuristics: probability + 2 (memo)");
714  }
715  else
716  {
717  const size_t match_memo_len = strlen(match_memo);
718  const size_t memo_len = strlen(memo);
719  const size_t max_memo_len = match_memo_len > memo_len ? match_memo_len : memo_len;
720  if (match_memo_len > 1 && memo_len > 1
721  && (strncasecmp(memo, match_memo, max_memo_len / 2) == 0))
722  {
723  /* Very primitive fuzzy match worth +1. This matches up to the
724  first 50% of the longest string to skip annoying transaction
725  number some banks seem to include in the memo but someone
726  should write something more sophisticated */
727  prob = prob + 1;
728  DEBUG("heuristics: probability + 1 (memo)");
729  }
730  }
731  }
732 
733  /* Description heuristics */
734  auto descr = xaccTransGetDescription(new_trans);
735  auto match_descr = xaccTransGetDescription(xaccSplitGetParent(split));
736  if (descr && *descr && match_descr && *match_descr)
737  {
738  DEBUG("description: download: '%s' to match: '%s'", descr, match_descr);
739  if (safe_strcasecmp(descr, match_descr) == 0)
740  {
741  /*An exact match of Description gives a +2 */
742  prob = prob + 2;
743  DEBUG("heuristics: probability + 2 (description)");
744  }
745  else
746  {
747  const size_t match_descr_len = strlen(match_descr);
748  const size_t descr_len = strlen(descr);
749  const size_t max_descr_len = match_descr_len > descr_len ? match_descr_len : descr_len;
750  if (match_descr_len > 1 && descr_len > 1
751  && (strncasecmp(descr, match_descr, max_descr_len / 2) == 0))
752  {
753  /* Very primitive fuzzy match worth +1. This matches up to the
754  first 50% of the longest string to skip annoying transaction
755  number some banks seem to include in the description but someone
756  should write something more sophisticated */
757  prob = prob + 1;
758  DEBUG("heuristics: probability + 1 (description)");
759  }
760  }
761  }
762 
763  /* Is the probability high enough? Otherwise do nothing and return. */
764  if (prob < display_threshold) {
765  DEBUG("below threshold: %d", prob);
766  return;
767  }
768 
769  /* The probability is high enough, so allocate an object
770  here. Allocating it only when it's actually being used is
771  probably quite some performance gain. */
772  auto match_info = g_new0(GNCImportMatchInfo, 1);
773 
774  match_info->probability = prob;
775  match_info->update_proposed = update_proposed;
776  match_info->split = split;
777  match_info->trans = xaccSplitGetParent(split);
778 
779 
780  /* Append that to the list. Do not use g_list_append because
781  it is slow. The list is sorted afterwards anyway. */
782  trans_info->match_list = g_list_prepend(trans_info->match_list, match_info);
783  DEBUG("Added to list of possible matches: %d", prob);
784 }
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
gint safe_strcasecmp(const gchar *da, const gchar *db)
case sensitive comparison of strings da and db - either may be NULL.
Definition: qofutil.cpp:100
Split * gnc_import_TransInfo_get_fsplit(const GNCImportTransInfo *info)
Returns the first split of the transaction of this TransInfo.
Transaction * gnc_import_TransInfo_get_trans(const GNCImportTransInfo *info)
Returns the transaction of this TransInfo.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
gdouble gnc_numeric_to_double(gnc_numeric n)
Convert numeric to floating-point value.
char * qof_print_date(time64 secs)
Convenience; calls through to qof_print_date_dmy_buff().
Definition: gnc-date.cpp:610
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
const char * xaccSplitGetMemo(const Split *split)
Returns the memo string.
Definition: gmock-Split.cpp:99
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account&#39;s commodity.
Definition: gmock-Split.cpp:69