gnucash maint: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Fri Dec 3 16:46:16 EST 2021


Updated	 via  https://github.com/Gnucash/gnucash/commit/ae7eaad0 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/8ad29fea (commit)
	from  https://github.com/Gnucash/gnucash/commit/6f09eae0 (commit)



commit ae7eaad018d0482fe2fcb8fb54c92c65f6663238
Merge: 6f09eae08 8ad29feab
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri Dec 3 13:44:50 2021 -0800

    Merge Chris Good's 'maintBug797678OfxAppend' into maint.


commit 8ad29feaba539f6bd90f558ac76d50671f808820
Author: goodvibes2 <goodchris96 at gmail.com>
Date:   Thu Sep 30 15:28:28 2021 +1000

    Bug797678 OFX import should append not replace, existing Notes & Desc
    
    Add an "Append" checkbox to the bottom of the "Generic import
    transaction matcher" window to the left of the "Reconcile after match"
    checkbox.
    When ticked, this causes the imported Description/Notes to be appended
    to the matched transaction Description/Notes respectively.
    The selected ticked/unticked state of the "Append" checkbox is saved in
    a key value pair for the import account, so the next import for that
    account will automatically default it to the saved state.
    As these mods are limited to the code for the matcher window, this
    should work for all the imports that use it - ie ofx & csv file imports
    (both tested) & aqbanking (cannot test).

diff --git a/gnucash/gtkbuilder/dialog-import.glade b/gnucash/gtkbuilder/dialog-import.glade
index b32a5f842..696a5fa60 100644
--- a/gnucash/gtkbuilder/dialog-import.glade
+++ b/gnucash/gtkbuilder/dialog-import.glade
@@ -960,7 +960,7 @@
         </child>
         <child>
           <object class="GtkCheckButton" id="show_matched_info_button">
-            <property name="label" translatable="yes">Show _matched information</property>
+            <property name="label" translatable="yes">Show matched _information</property>
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">False</property>
@@ -973,9 +973,25 @@
             <property name="position">2</property>
           </packing>
         </child>
+        <child>
+          <object class="GtkCheckButton" id="append_desc_notes_button">
+            <property name="label" translatable="yes">A_ppend</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">False</property>
+            <property name="tooltip_text" translatable="yes">When Updating and Clearing a matched transaction, append the imported Description and Notes to the matched Description and Notes instead of replacing them.</property>
+            <property name="use_underline">True</property>
+            <property name="draw_indicator">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">3</property>
+          </packing>
+        </child>    
         <child>
           <object class="GtkCheckButton" id="reconcile_after_close_button">
-            <property name="label" translatable="yes">Reconcile after match</property>
+            <property name="label" translatable="yes">_Reconcile after match</property>
             <property name="can_focus">True</property>
             <property name="receives_default">False</property>
             <property name="no_show_all">True</property>
@@ -985,7 +1001,7 @@
           <packing>
             <property name="expand">False</property>
             <property name="fill">True</property>
-            <property name="position">3</property>
+            <property name="position">4</property>
           </packing>
         </child>
       </object>
diff --git a/gnucash/import-export/import-backend.c b/gnucash/import-export/import-backend.c
index d9f86f6cc..c17487a22 100644
--- a/gnucash/import-export/import-backend.c
+++ b/gnucash/import-export/import-backend.c
@@ -95,6 +95,9 @@ struct _transactioninfo
 
     /* Reference id to link gnc transaction to external object. E.g. aqbanking job id. */
     guint32 ref_id;
+
+    /* When updating a matched transaction, append Description and Notes instead of replacing */
+    gboolean append_text;
 };
 
 /* Some simple getters and setters for the above data types. */
@@ -240,6 +243,15 @@ gnc_import_TransInfo_set_ref_id (GNCImportTransInfo *info,
 }
 
 
+void
+gnc_import_TransInfo_set_append_text (GNCImportTransInfo *info,
+                                      gboolean append_text)
+{
+    g_assert (info);
+    info->append_text = append_text;
+}
+
+
 Split *
 gnc_import_MatchInfo_get_split (const GNCImportMatchInfo * info)
 {
@@ -827,6 +839,77 @@ void split_find_match (GNCImportTransInfo * trans_info,
 /***********************************************************************
  */
 
+/* append the imported transaction description to the matched transaction description */
+static void
+desc_append (Transaction* selected_match_trans, Transaction* imp_trans)
+{
+    gchar* tmp = g_strconcat( xaccTransGetDescription (selected_match_trans),
+                              "|",
+                              xaccTransGetDescription (imp_trans),
+                              NULL);
+    xaccTransSetDescription (selected_match_trans, tmp);
+    g_free (tmp);
+}
+
+/* append the imported transaction notes to the matched transaction notes */
+static void
+notes_append (Transaction* selected_match_trans, Transaction* imp_trans)
+{
+    gchar* tmp = g_strconcat (xaccTransGetNotes (selected_match_trans),
+                              "|",
+                              xaccTransGetNotes (imp_trans),
+                              NULL);
+    xaccTransSetNotes (selected_match_trans, tmp);
+    g_free (tmp);
+}
+
+/* Append or replace transaction description and notes
+ * depending on the Append checkbox
+ */
+static void
+update_desc_and_notes (const GNCImportTransInfo* trans_info)
+{
+    GNCImportMatchInfo* selected_match =
+            gnc_import_TransInfo_get_selected_match (trans_info);
+    Transaction* imp_trans = gnc_import_TransInfo_get_trans (trans_info);
+
+    if (trans_info->append_text)
+    {
+        gchar* desc_imported = g_utf8_normalize (xaccTransGetDescription (
+            imp_trans), -1, G_NORMALIZE_ALL);
+        gchar* desc_matched = g_utf8_normalize (xaccTransGetDescription (
+            selected_match->trans), -1, G_NORMALIZE_ALL);
+        gchar* note_imported = g_utf8_normalize (xaccTransGetNotes (
+                imp_trans), -1, G_NORMALIZE_ALL);
+        gchar* note_matched = g_utf8_normalize (xaccTransGetNotes (
+            selected_match->trans), -1, G_NORMALIZE_ALL);
+
+        // Append if desc_imported not already in desc_matched
+        if (g_utf8_strlen (desc_imported, -1) > g_utf8_strlen (desc_matched, -1) ||
+            !strstr (desc_matched, desc_imported))
+            desc_append (selected_match->trans, imp_trans);
+
+        // Append if note_imported not already in note_matched
+        if (g_utf8_strlen (note_imported, -1) > g_utf8_strlen (note_matched, -1) ||
+            !strstr (note_matched, note_imported))
+            notes_append (selected_match->trans, imp_trans);
+
+        g_free(desc_imported);
+        g_free(desc_matched);
+        g_free(note_imported);
+        g_free(note_matched);
+    }
+    else
+    {
+        // replace the matched transaction description with the imported transaction description
+        xaccTransSetDescription (selected_match->trans,
+                                 xaccTransGetDescription (imp_trans));
+        // replace the matched transaction notes with the imported transaction notes
+        xaccTransSetNotes (selected_match->trans,
+                           xaccTransGetNotes (imp_trans));
+    }
+}
+
 /** /brief -- Processes one match
    according to its selected action.  */
 gboolean
@@ -944,13 +1027,7 @@ gnc_import_process_trans_item (GncImportMatchMap *matchmap,
                    to balance the transaction */
             }
 
-            xaccTransSetDescription(selected_match->trans,
-                                    xaccTransGetDescription(
-                                        gnc_import_TransInfo_get_trans(trans_info)));
-
-            xaccTransSetNotes(selected_match->trans,
-                                    xaccTransGetNotes(
-                                        gnc_import_TransInfo_get_trans(trans_info)));
+            update_desc_and_notes( trans_info);
 
             if (xaccSplitGetReconcile(selected_match->split) == NREC)
             {
diff --git a/gnucash/import-export/import-backend.h b/gnucash/import-export/import-backend.h
index b524d1835..cb9c72663 100644
--- a/gnucash/import-export/import-backend.h
+++ b/gnucash/import-export/import-backend.h
@@ -238,6 +238,11 @@ void
 gnc_import_TransInfo_set_ref_id (GNCImportTransInfo *info,
                                  guint32 ref_id);
 
+/** Set the append_text for this TransInfo. */
+void
+gnc_import_TransInfo_set_append_text (GNCImportTransInfo *info,
+                                           gboolean append_text);
+
 /**@}*/
 
 /** @name Getters/Setters for GNCImportMatchInfo */
diff --git a/gnucash/import-export/import-main-matcher.c b/gnucash/import-export/import-main-matcher.c
index e6c9df361..c0f11ae33 100644
--- a/gnucash/import-export/import-main-matcher.c
+++ b/gnucash/import-export/import-main-matcher.c
@@ -72,6 +72,7 @@ struct _main_matcher_info
     GtkTreeViewColumn       *memo_column;
     GtkWidget               *show_account_column;
     GtkWidget               *show_matched_info;
+    GtkWidget               *append_text; // Update+Clear: Append import Desc/Notes to matched Desc/Notes
     GtkWidget               *reconcile_after_close;
     gboolean add_toggled;     // flag to indicate that add has been toggled to stop selection
     gint id;
@@ -444,7 +445,22 @@ resolve_conflicts (GNCImportMainMatcher *info)
 void
 gnc_gen_trans_list_show_all (GNCImportMainMatcher *info)
 {
+    GNCImportTransInfo* trans_info;
+    Account* account;
+    Split* first_split;
+    GSList* temp_trans_list;
+
     g_assert (info);
+
+    // Set initial state of Append checkbox to same as last import for this account.
+    // Get the import account from the first split in first transaction.
+    temp_trans_list = info->temp_trans_list;
+    trans_info = temp_trans_list->data;
+    first_split = gnc_import_TransInfo_get_fsplit (trans_info);
+    account = xaccSplitGetAccount(first_split);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (info->append_text),
+                                 xaccAccountGetAppendText(account));
+
     gnc_gen_trans_list_create_matches (info);
     resolve_conflicts (info);
     gtk_widget_show_all (GTK_WIDGET(info->main_widget));
@@ -457,6 +473,9 @@ on_matcher_ok_clicked (GtkButton *button, GNCImportMainMatcher *info)
     GtkTreeModel *model;
     GtkTreeIter iter;
     GNCImportTransInfo *trans_info;
+    gboolean append_text = gtk_toggle_button_get_active ((GtkToggleButton*) info->append_text);
+    gboolean first_tran = TRUE;
+    gpointer user_data = info->user_data;
 
     g_assert (info);
 
@@ -479,6 +498,20 @@ on_matcher_ok_clicked (GtkButton *button, GNCImportMainMatcher *info)
                             DOWNLOADED_COL_DATA, &trans_info,
                             -1);
 
+        // Allow the backend to know if the Append checkbox is ticked or unticked
+        // by propagating info->append_text to every trans_info->append_text
+        gnc_import_TransInfo_set_append_text( trans_info, append_text);
+
+        // When processing the first transaction,
+        // save the state of the Append checkbox to an account kvp so the same state can be
+        //  defaulted next time this account is imported.
+        // Get the import account from the first split.
+        if (first_tran)
+        {
+            Split* first_split = gnc_import_TransInfo_get_fsplit (trans_info);
+            xaccAccountSetAppendText (xaccSplitGetAccount(first_split), append_text);
+            first_tran = FALSE;
+        }
         // Note: if there's only 1 split (unbalanced) one will be created with the unbalanced account,
         // and for that account the defer balance will not be set. So things will be slow.
 
@@ -1222,7 +1255,9 @@ gnc_gen_trans_common_setup (GNCImportMainMatcher *info,
     g_signal_connect (G_OBJECT(info->show_matched_info), "toggled",
                       G_CALLBACK(show_matched_info_toggled_cb), info);
 
-    // Create the checkbox, but do not show it by default.
+    info->append_text = GTK_WIDGET(gtk_builder_get_object (builder, "append_desc_notes_button"));
+
+    // Create the checkbox, but do not show it unless there are transactions
     info->reconcile_after_close = GTK_WIDGET(gtk_builder_get_object (builder, "reconcile_after_close_button"));
 
     show_update = gnc_import_Settings_get_action_update_enabled (info->user_settings);
@@ -1905,6 +1940,13 @@ gnc_gen_trans_list_widget (GNCImportMainMatcher *info)
     return info->main_widget;
 }
 
+GtkWidget *
+gnc_gen_trans_list_append_text_widget (GNCImportMainMatcher *info)
+{
+    g_assert (info);
+    return info->append_text;
+}
+
 gboolean
 query_tooltip_tree_view_cb (GtkWidget *widget, gint x, gint y,
                             gboolean keyboard_tip,
diff --git a/gnucash/import-export/import-main-matcher.h b/gnucash/import-export/import-main-matcher.h
index 6b20c3d4f..490d54c44 100644
--- a/gnucash/import-export/import-main-matcher.h
+++ b/gnucash/import-export/import-main-matcher.h
@@ -189,6 +189,13 @@ gboolean gnc_gen_trans_list_run (GNCImportMainMatcher *info);
  */
 GtkWidget *gnc_gen_trans_list_widget (GNCImportMainMatcher *info);
 
+/** Returns the append_text widget of this dialog.
+ * @param info A pointer to a the GNCImportMainMatcher structure.
+ * @return A GtkWidget pointer to the append_text widget.
+ */
+GtkWidget *
+gnc_gen_trans_list_append_text_widget (GNCImportMainMatcher *info);
+
 /** Checks whether there are no transactions to match.
  * @param info A pointer to a the GNCImportMainMatcher structure.
  * @return A boolean indicating whether the transaction list is empty.
diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp
index 03e461d59..ee375d304 100644
--- a/libgnucash/engine/Account.cpp
+++ b/libgnucash/engine/Account.cpp
@@ -65,6 +65,7 @@ static const std::string KEY_INCLUDE_CHILDREN("include-children");
 static const std::string KEY_POSTPONE("postpone");
 static const std::string KEY_LOT_MGMT("lot-mgmt");
 static const std::string KEY_ONLINE_ID("online_id");
+static const std::string KEY_IMP_APPEND_TEXT("import-append-text");
 static const std::string AB_KEY("hbci");
 static const std::string AB_ACCOUNT_ID("account-id");
 static const std::string AB_ACCOUNT_UID("account-uid");
@@ -116,6 +117,7 @@ enum
 
     PROP_LOT_NEXT_ID,                   /* KVP */
     PROP_ONLINE_ACCOUNT,                /* KVP */
+    PROP_IMP_APPEND_TEXT,               /* KVP */
     PROP_IS_OPENING_BALANCE,            /* KVP */
     PROP_OFX_INCOME_ACCOUNT,            /* KVP */
     PROP_AB_ACCOUNT_ID,                 /* KVP */
@@ -484,6 +486,9 @@ gnc_account_get_property (GObject         *object,
     case PROP_ONLINE_ACCOUNT:
         qof_instance_get_path_kvp (QOF_INSTANCE (account), value, {KEY_ONLINE_ID});
         break;
+    case PROP_IMP_APPEND_TEXT:
+        g_value_set_boolean(value, xaccAccountGetAppendText(account));
+        break;
     case PROP_OFX_INCOME_ACCOUNT:
         qof_instance_get_path_kvp (QOF_INSTANCE (account), value, {KEY_ASSOC_INCOME_ACCOUNT});
         break;
@@ -613,6 +618,9 @@ gnc_account_set_property (GObject         *object,
     case PROP_ONLINE_ACCOUNT:
         qof_instance_set_path_kvp (QOF_INSTANCE (account), value, {KEY_ONLINE_ID});
         break;
+    case PROP_IMP_APPEND_TEXT:
+        xaccAccountSetAppendText(account, g_value_get_boolean(value));
+        break;
     case PROP_OFX_INCOME_ACCOUNT:
         qof_instance_set_path_kvp (QOF_INSTANCE (account), value, {KEY_ASSOC_INCOME_ACCOUNT});
         break;
@@ -1062,6 +1070,16 @@ gnc_account_class_init (AccountClass *klass)
                           NULL,
                           static_cast<GParamFlags>(G_PARAM_READWRITE)));
 
+    g_object_class_install_property
+    (gobject_class,
+     PROP_IMP_APPEND_TEXT,
+     g_param_spec_boolean ("import-append-text",
+                           "Import Append Text",
+                           "Saved state of Append checkbox for setting initial "
+                           "value next time this account is imported.",
+                           FALSE,
+                           static_cast<GParamFlags>(G_PARAM_READWRITE)));
+
      g_object_class_install_property(
        gobject_class,
        PROP_OFX_INCOME_ACCOUNT,
@@ -4228,6 +4246,18 @@ xaccAccountSetPlaceholder (Account *acc, gboolean val)
     set_boolean_key(acc, {"placeholder"}, val);
 }
 
+gboolean
+xaccAccountGetAppendText (const Account *acc)
+{
+    return boolean_from_key(acc, {"import-append-text"});
+}
+
+void
+xaccAccountSetAppendText (Account *acc, gboolean val)
+{
+    set_boolean_key(acc, {"import-append-text"}, val);
+}
+
 gboolean
 xaccAccountGetIsOpeningBalance (const Account *acc)
 {
diff --git a/libgnucash/engine/Account.h b/libgnucash/engine/Account.h
index 6822bfd65..19093036c 100644
--- a/libgnucash/engine/Account.h
+++ b/libgnucash/engine/Account.h
@@ -1217,6 +1217,30 @@ gboolean xaccAccountGetPlaceholder (const Account *account);
  *  @param val The new state for the account's "placeholder" flag. */
 void xaccAccountSetPlaceholder (Account *account, gboolean val);
 
+/** @name Account Append Text flag
+ @{
+*/
+
+/** Get the "import-append-text" flag for an account.  This is the saved
+ *  state of the Append checkbox in the "Generic import transaction matcher"
+ *  used to set the initial state of the Append checkbox next time this
+ *  account is imported.
+ *
+ *  @param account The account whose flag should be retrieved.
+ *
+ *  @return The current state of the account's "import-append-text" flag. */
+gboolean xaccAccountGetAppendText (const Account *account);
+
+/** Set the "import-append-text" flag for an account.  This is the saved
+ *  state of the Append checkbox in the "Generic import transaction matcher"
+ *  used to set the initial state of the Append checkbox next time this
+ *  account is imported.
+ *
+ *  @param account The account whose flag should be retrieved.
+ *
+ *  @param val The new state for the account's "import-append-text" flag. */
+void xaccAccountSetAppendText (Account *account, gboolean val);
+
 /** Get the "opening-balance" flag for an account.  If this flag is set
  *  then the account is used for opening balance transactions.
  *



Summary of changes:
 gnucash/gtkbuilder/dialog-import.glade      | 22 ++++++-
 gnucash/import-export/import-backend.c      | 91 ++++++++++++++++++++++++++---
 gnucash/import-export/import-backend.h      |  5 ++
 gnucash/import-export/import-main-matcher.c | 44 +++++++++++++-
 gnucash/import-export/import-main-matcher.h |  7 +++
 libgnucash/engine/Account.cpp               | 30 ++++++++++
 libgnucash/engine/Account.h                 | 24 ++++++++
 7 files changed, 212 insertions(+), 11 deletions(-)



More information about the gnucash-changes mailing list