gnucash maint: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Thu Apr 25 16:29:07 EDT 2019


Updated	 via  https://github.com/Gnucash/gnucash/commit/483f9a4c (commit)
	 via  https://github.com/Gnucash/gnucash/commit/5311e5a3 (commit)
	from  https://github.com/Gnucash/gnucash/commit/0cf49f12 (commit)



commit 483f9a4c8331f82e8f13f51a52b5d51339d13557
Author: thetedmunds <tedmunds at gmail.com>
Date:   Mon Apr 15 14:31:23 2019 -0700

    Bug 797196 - Allow for per-payment rounding in amortization calculations
    
    Provides functions gnc:amort_pmt, gnc:amort_ppmt, and gnc:amort_ipmt in
    fin.scm.

diff --git a/libgnucash/app-utils/fin.scm b/libgnucash/app-utils/fin.scm
index a8edf0506..4ffc3c1fa 100644
--- a/libgnucash/app-utils/fin.scm
+++ b/libgnucash/app-utils/fin.scm
@@ -182,3 +182,171 @@
     )
   )
 )
+
+;; Further options to match what some (several? many?) lenders do (at
+;;  least in Canada):
+;; The posted interest rate is an annual rate that has a specified
+;;  compounding frequency per year (2 for mortgages in Canada).
+;; A payment frequency and amortization length are selected (e.g.
+;;  monthly payments for 25 years).
+;; The posted nominal rate is converted from the specified compounding
+;;  frequency to the equivalent rate at the payment frequency.
+;; The required payment is calculated.
+;; The payment is rounded up to the next dollar (or $10 dollars,
+;;  or whatever...)
+;; Each payment period, interest is calculated on the outstanding
+;;  balance.
+;; The interest is rounded to the nearest cent and added to the
+;;  balance.
+;; The payment is subtracted from the balance.
+;; The final payment will be smaller because all the other payments
+;;  were rounded up.
+;;
+;; For the purpose of creating scheduled transactions that properly
+;;  debit a source account while crediting the loan account and the
+;;  interest expense account, the first part (the calculation of the
+;;  required payment) doesn't really matter.  You have agreed
+;;  with the lender what the payment terms (interest rate, payment
+;;  frequency, payment amount) will be; you keep paying until the
+;;  balance is zero.
+;;
+;; To create the scheduled transactions, we need to build an
+;;  amortization table.
+;; If it weren't for the rounding of the interest to the nearest cent
+;;  each period, we could calculate the ith row of the amortization
+;;  table directly from the general annuity equation (as is done by
+;;  gnc:ipmt and gnc:ppmt).  But to deal with the intermediate
+;;  rounding, the amortization table has to be constructed iteratively
+;;  (as is done by the AMORT worksheet on the TI BA II Plus
+;;  financial calculator).
+;;
+;; =================================
+;; EXAMPLE:
+;; Say you borrow $100,000 at 5%/yr, compounded semi-annually.
+;; You amortize the loan over 2 years with 24 monthly payments.
+;; This calls for payments of $4,384.8418 at the end of each month.
+;; The lender rounds this up to $4,385.
+;;
+;; If you calculate the balance at each period directly using the annuity
+;; formula (like calc-principal does), and then use the those values to calculate
+;; the principal and interest paid, the first 10 rows of the amortization table
+;; look like this (the values are rounded to the nearest cent for _display_, but
+;; not for calculating the next period):
+;;
+;; PERIOD | Open       | Interest | Principal | End
+;;    1   |$100,000.00 |  $412.39 | $3,972.61 | $96,027.39
+;;    2   | $96,027.39 |  $396.01 | $3,988.99 | $92,038.40 
+;;    3   | $92,038.40 |  $379.56 | $4,005.44 | $88,032.96 
+;;    4   | $88,032.96 |  $363.04 | $4,021.96 | $84,011.00 
+;;    5   | $84,011.00 |  $346.45 | $4,038.55 | $79,972.45 
+;;    6   | $79,972.45 |  $329.80 | $4,055.20 | $75,917.25 
+;;    7   | $75,917.25 |  $313.08 | $4,071.92 | $71,845.33 
+;;    8   | $71,845.33 |  $296.28 | $4,088.72 | $67,756.61 
+;;    9   | $67,756.61 |  $279.43 | $4,105.57 | $63,651.04 
+;;   10   | $63,651.04 |  $262.49 | $4,122.51 | $59,528.53
+;;
+;; If you calculate each period sequentially (rounding the interest and balance
+;; at each step), you get:
+;;
+;; PERIOD | Open       | Interest | Principal | End
+;;    1   |$100,000.00 |  $412.39 | $3,972.61 | $96,027.39
+;;    2   | $96,027.39 |  $396.01 | $3,988.99 | $92,038.40 
+;;    3   | $92,038.40 |  $379.56 | $4,005.44 | $88,032.96 
+;;    4   | $88,032.96 |  $363.04 | $4,021.96 | $84,011.00 
+;;    5   | $84,011.00 |  $346.45 | $4,038.55 | $79,972.45 
+;;    6   | $79,972.45 |  $329.80 | $4,055.20 | $75,917.25 
+;;    7   | $75,917.25 |  $313.08 | $4,071.92 | $71,845.33 
+;;    8   | $71,845.33 |  $296.28 | $4,088.72 | $67,756.61 
+;;    9   | $67,756.61 |  $279.42 | $4,105.58 | $63,651.03 <- Different 
+;;   10   | $63,651.03 |  $262.49 | $4,122.51 | $59,528.52 <- still $0.01 off
+;;
+;; =================================
+;;
+;; For the following functions the argument names are:
+;;  py: payment frequency (number of payments per year)
+;;  cy: compounding frequency of the nominal rate (per year)
+;;  iy: nominal annual interest rate
+;;  pv: the present value (opening balance)
+;;  pmt: the size of the periodic payment
+;;  n: the payment period we are asking about (the first payment is n=1)
+;;  places: number of decimal places to round the interest amount to 
+;;          at each payment (999 does no rounding)
+;;
+;; Note: only ordinary annuities are supported (payments at the end of
+;;  each period, not at the beginning of each period)
+;;
+;; Unlike the AMORT worksheet on the BA II Plus, these methods will
+;;  handle the smaller payment (bringing the balance to zero, then
+;;  zeroing future payments)
+;;
+;; The present value (pv) must be non-negative.  If not, the balance will be
+;;  treated as 0.
+;; The payment (pmt) can be positive (paying interest, and hopefully
+;;  reducing the balance each payment), or negative (increasing the balance
+;   each payment).
+;; The payment number (n) must be positive for amort_pmt, amort_ppmt, and
+;;  amort_ipmt.  I.e., the first payment is payment 1.
+;; The payment number (n) must be non-negative for amort_balance.  (In this
+;;  case, payment zero is at the _beginning_ of the first period, so
+;;  amort_balance will just be the initial balance.)
+;; If the above conditions on n are violated, the functions return -1 (#f is
+;;  not used, because it causes gnucash to crash).
+;;
+;; A negative interest rate works (if you can find a lender who charges
+;;  negative rates), but negative compounding frequency, or negative payment
+;;  frequency is a bad idea.
+
+;; Calculate the balance remaining after the nth payment
+;; (n must be greater than or equal to zero)
+(define (gnc:amort_pmt py cy iy pv pmt n places)
+  (if (< n 1) -1 ;; Returning #f here causes gnucash to crash on startup
+    (let* ((prevBal (gnc:amort_balance py cy iy pv pmt (- n 1) places))
+           (balBeforePayment
+		     (amort_balanceAfterInterest prevBal py cy iy places))
+           (balAfterPayment (amort_balanceAfterPayment balBeforePayment pmt)))
+      (- balBeforePayment balAfterPayment))))
+
+;; Calculate the amount of the nth payment that is principal
+;; (n must be greater than zero)
+(define (gnc:amort_ppmt py cy iy pv pmt n places)
+  (if (< n 1) -1
+    (let* ((prevBal (gnc:amort_balance py cy iy pv pmt (- n 1) places))
+	       (bal-after-int (amort_balanceAfterInterest prevBal py cy iy places))
+           (newBal (amort_balanceAfterPayment bal-after-int pmt)))
+      (- prevBal newBal))))
+
+;; Calculate the amount of the nth payment that is interest
+;; (n must be greater than zero)
+(define (gnc:amort_ipmt py cy iy pv pmt n places)
+  (if (< n 1) -1
+    (let* ((prevBal(gnc:amort_balance py cy iy pv pmt (- n 1) places)))
+      (amort_interest prevBal py cy iy places))))
+
+;; "Private" helper functions:
+
+;; Calculate the amount of interest on the current balance,
+;; rounded to the specified number of decimal places
+(define (amort_interest balance py cy iy places)
+  (roundToPlaces (* balance (gnc:periodic_rate iy py cy)) places)
+)
+
+;; Calculate the new balance after applying the interest, but before
+;; applying the payment
+(define (amort_balanceAfterInterest prevBalance py cy iy places)
+  (+ prevBalance (amort_interest prevBalance py cy iy places))
+)
+
+;; Apply the payment to the balance (after the interest has been
+;; added), without letting the balance go below zero.
+(define (amort_balanceAfterPayment balanceBeforePmt pmt)
+  (max 0 (- balanceBeforePmt pmt))
+)
+
+;; Round the value to the specified number of decimal places.
+;; 999 places means no rounding (#f is not used, because only numbers can be
+;; entered in the scheduled transaction editor)
+(define (roundToPlaces value places)
+  (if (= places 999) value
+    (/ (round (* value (expt 10 places))) (expt 10 places))
+  )
+)

commit 5311e5a386e48a07a8d4dbc8f032750a9ca76bf7
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Apr 25 13:19:28 2019 -0700

    Revert "Merge T Edmunds's 'amortization-rounding' into maint."
    
    This reverts commit aa53c23239dc05da44c78a085c4db342adfbf707, reversing
    changes made to 3c946a84496a846196ba04667e3a7f0c7bee0eb5, because
    aa53c23 was based on master and so undid other changes made to maint
    since the last merge-to-master.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 903ebcc5d..23eb5e9ed 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,13 +12,13 @@ enable_testing()
 
 # Version number of gnucash
 set (GNUCASH_MAJOR_VERSION 3)
-set (GNUCASH_MINOR_VERSION 900)
+set (GNUCASH_MINOR_VERSION 5)
 set (VERSION "${GNUCASH_MAJOR_VERSION}.${GNUCASH_MINOR_VERSION}")
 set (GNUCASH_LATEST_STABLE_SERIES 3.x)
 
 set (PACKAGE gnucash)
 set (PACKAGE_NAME GnuCash)
-set (PACKAGE_VERSION 3.900)
+set (PACKAGE_VERSION 3.5)
 set (PACKAGE_BUGREPORT "https://bugs.gnucash.org")
 set (PACKAGE_TARNAME ${PACKAGE})
 set (PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
diff --git a/gnucash/gtkbuilder/dialog-import.glade b/gnucash/gtkbuilder/dialog-import.glade
index fd8935b5a..59ed257be 100644
--- a/gnucash/gtkbuilder/dialog-import.glade
+++ b/gnucash/gtkbuilder/dialog-import.glade
@@ -14,9 +14,6 @@
     <property name="default_height">600</property>
     <property name="type_hint">dialog</property>
     <signal name="map" handler="gnc_ui_generic_account_picker_map_cb" swapped="no"/>
-    <child>
-      <placeholder/>
-    </child>
     <child internal-child="vbox">
       <object class="GtkBox" id="account_picker_vbox">
         <property name="visible">True</property>
@@ -168,6 +165,7 @@
     <property name="page_increment">10</property>
   </object>
   <object class="GtkDialog" id="format_picker_dialog">
+    <property name="visible">False</property>
     <property name="can_focus">False</property>
     <property name="title" translatable="yes">Choose a format</property>
     <property name="resizable">False</property>
@@ -175,9 +173,6 @@
     <property name="default_width">600</property>
     <property name="default_height">400</property>
     <property name="type_hint">dialog</property>
-    <child>
-      <placeholder/>
-    </child>
     <child internal-child="vbox">
       <object class="GtkBox" id="dialog-vbox16">
         <property name="visible">True</property>
@@ -306,9 +301,6 @@
     <property name="visible">True</property>
     <property name="can_focus">False</property>
     <property name="title" translatable="yes">Preferences</property>
-    <child>
-      <placeholder/>
-    </child>
     <child>
       <object class="GtkGrid" id="matcher_prefs">
         <property name="visible">True</property>
@@ -562,9 +554,6 @@
     <property name="default_width">600</property>
     <property name="default_height">400</property>
     <property name="type_hint">dialog</property>
-    <child>
-      <placeholder/>
-    </child>
     <child internal-child="vbox">
       <object class="GtkBox" id="dialog-vbox14">
         <property name="visible">True</property>
@@ -728,8 +717,7 @@
     <property name="text" translatable="yes">This transaction requires your intervention or it will NOT be imported.</property>
   </object>
   <object class="GtkTextBuffer" id="textbuffer5">
-    <property name="text" translatable="yes">Double click on the transaction to change the matching transaction to reconcile, or the destination account of the auto-balance split (if required).
-Multiply select rows using Ctrl-Click, Shift-Click and Rubber banding . Right-Click or Shift-F10 to bring up popup menu and click or select to assign a destination account to the selected rows.</property>
+    <property name="text" translatable="yes">Double click on the transaction to change the matching transaction to reconcile, or the destination account of the auto-balance split (if required).</property>
   </object>
   <object class="GtkDialog" id="matcher_help_dialog">
     <property name="can_focus">False</property>
@@ -738,9 +726,6 @@ Multiply select rows using Ctrl-Click, Shift-Click and Rubber banding . Right-Cl
     <property name="resizable">False</property>
     <property name="type_hint">dialog</property>
     <signal name="close" handler="on_matcher_help_close_clicked" swapped="no"/>
-    <child>
-      <placeholder/>
-    </child>
     <child internal-child="vbox">
       <object class="GtkBox" id="dialog-vbox18">
         <property name="visible">True</property>
@@ -779,7 +764,6 @@ Multiply select rows using Ctrl-Click, Shift-Click and Rubber banding . Right-Cl
           <object class="GtkGrid" id="table1">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="margin_bottom">42</property>
             <property name="row_spacing">6</property>
             <property name="column_spacing">12</property>
             <child>
@@ -1006,7 +990,6 @@ Multiply select rows using Ctrl-Click, Shift-Click and Rubber banding . Right-Cl
                   <object class="GtkTextView" id="textview5">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
-                    <property name="margin_bottom">2</property>
                     <property name="pixels_above_lines">5</property>
                     <property name="pixels_below_lines">5</property>
                     <property name="editable">False</property>
@@ -1124,11 +1107,8 @@ Multiply select rows using Ctrl-Click, Shift-Click and Rubber banding . Right-Cl
             <property name="reorderable">True</property>
             <property name="rules_hint">True</property>
             <property name="enable_search">False</property>
-            <property name="rubber_banding">True</property>
             <child internal-child="selection">
-              <object class="GtkTreeSelection" id="treeview-selection3">
-                <property name="mode">multiple</property>
-              </object>
+              <object class="GtkTreeSelection" id="treeview-selection3"/>
             </child>
           </object>
         </child>
@@ -1165,9 +1145,6 @@ Multiply select rows using Ctrl-Click, Shift-Click and Rubber banding . Right-Cl
     <property name="default_height">400</property>
     <property name="type_hint">dialog</property>
     <signal name="close" handler="on_matcher_cancel_clicked" swapped="no"/>
-    <child>
-      <placeholder/>
-    </child>
     <child internal-child="vbox">
       <object class="GtkBox" id="transaction_matcher_vbox">
         <property name="visible">True</property>
diff --git a/gnucash/import-export/import-main-matcher.c b/gnucash/import-export/import-main-matcher.c
index 7172c52e2..773429602 100644
--- a/gnucash/import-export/import-main-matcher.c
+++ b/gnucash/import-export/import-main-matcher.c
@@ -98,28 +98,9 @@ void on_matcher_help_clicked (GtkButton *button, gpointer user_data);
 void on_matcher_help_close_clicked (GtkButton *button, gpointer user_data);
 
 /* Local prototypes */
-static void gnc_gen_trans_assign_transfer_account(
-                                                GtkTreeView *treeview, 
-                                                gboolean *first,
-                                                gboolean *is_selection,
-                                                GtkTreePath *path,
-                                                Account **new_acc,
-                                                GNCImportMainMatcher *info);
-static void gnc_gen_trans_assign_transfer_account_to_selection_cb (
-                                          GtkMenuItem *menuitem,
-                                          GNCImportMainMatcher *info);
-static void gnc_gen_trans_view_popup_menu (GtkTreeView *treeview, 
-                                          GdkEvent *event,
-                                          GNCImportMainMatcher *info);
-static gboolean gnc_gen_trans_onButtonPressed_cb (GtkTreeView *treeview,
-                                                  GdkEvent *event,
-                                                  GNCImportMainMatcher *info);
-static gboolean gnc_gen_trans_onPopupMenu_cb (GtkTreeView *treeview,
-                                              GdkEvent *event, 
-                                              GNCImportMainMatcher *info);
-static void refresh_model_row(GNCImportMainMatcher *gui, GtkTreeModel *model,
+static void
+refresh_model_row(GNCImportMainMatcher *gui, GtkTreeModel *model,
                   GtkTreeIter *iter, GNCImportTransInfo *info);
-/* end local prototypes */
 
 void gnc_gen_trans_list_delete (GNCImportMainMatcher *info)
 {
@@ -380,238 +361,54 @@ gnc_gen_trans_update_toggled_cb (GtkCellRendererToggle *cell_renderer,
 }
 
 static void
-gnc_gen_trans_assign_transfer_account(GtkTreeView *treeview, 
-                                      gboolean *first,
-                                      gboolean *is_selection,
-                                      GtkTreePath *path,
-                                      Account **new_acc,
-                                      GNCImportMainMatcher *info)
+gnc_gen_trans_row_activated_cb (GtkTreeView           *view,
+                                GtkTreePath           *path,
+                                GtkTreeViewColumn     *column,
+                                GNCImportMainMatcher  *gui)
 {
     GtkTreeModel *model;
     GtkTreeIter iter;
     GNCImportTransInfo *trans_info;
-    Account *old_acc;
-    gboolean ok_pressed;
 
-    ENTER("");
-    DEBUG("first = %s",*first?"true":"false");
-    DEBUG("is_selection = %s",*is_selection?"true":"false");
-    DEBUG("path  = %s", gtk_tree_path_to_string(path));
-    DEBUG("account passed in = %s", gnc_get_account_name_for_register(*new_acc));
-    model = gtk_tree_view_get_model(treeview);
-    if (gtk_tree_model_get_iter(model, &iter, path))
-    {
-        gtk_tree_model_get(model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1);
+    model = gtk_tree_view_get_model(gui->view);
+    if (!gtk_tree_model_get_iter(model, &iter, path))
+        return;
+    gtk_tree_model_get(model, &iter, DOWNLOADED_COL_DATA, &trans_info, -1);
 
-        switch (gnc_import_TransInfo_get_action (trans_info))
+    switch (gnc_import_TransInfo_get_action (trans_info))
+    {
+    case GNCImport_ADD:
+        if (gnc_import_TransInfo_is_balanced(trans_info) == FALSE)
         {
-        case GNCImport_ADD:
-            if (gnc_import_TransInfo_is_balanced(trans_info) == FALSE)
-            {
-                ok_pressed = TRUE;
-                old_acc  = gnc_import_TransInfo_get_destacc (trans_info);
-                if (*first)
-                {
-                    ok_pressed = FALSE;
-                    *new_acc = gnc_import_select_account(info->main_widget,
-                        NULL,
-                        TRUE,
-                        _("Destination account for the auto-balance split."),
-                        xaccTransGetCurrency(
-                              gnc_import_TransInfo_get_trans(trans_info)),
-                        ACCT_TYPE_NONE,
-                        old_acc,
-                        &ok_pressed);
-                    *first = FALSE;
-                    DEBUG("account selected = %s", 
-                            gnc_account_get_full_name(*new_acc));                    
-                }
-                if (ok_pressed)
-                        gnc_import_TransInfo_set_destacc (trans_info, 
-                                                    *new_acc, TRUE);
-            }
-            break;
-        case GNCImport_CLEAR:
-        case GNCImport_UPDATE:
-            if (first && !is_selection) run_match_dialog (info, trans_info);
-            break;
-        case GNCImport_SKIP:        
-            break;
-        default:
-            PERR("InvalidGNCImportValue");
-            break;
+            run_account_picker_dialog (gui, model, &iter, trans_info);
         }
-        refresh_model_row(info, model, &iter, trans_info);
-    }
-    LEAVE("");
-}
-
-static void
-gnc_gen_trans_assign_transfer_account_to_selection_cb (GtkMenuItem *menuitem,
-                                             GNCImportMainMatcher *info)
-{
-    GtkTreeView *treeview;
-    GtkTreeSelection *selection;
-    GtkTreeModel *model;
-    GtkTreeIter iter;
-    GNCImportTransInfo *trans_info;
-    Account *assigned_account;
-    GList *selected_rows, *l;
-    gboolean first, is_selection;
-
-    ENTER("");
-    treeview = GTK_TREE_VIEW(info->view);
-    model = gtk_tree_view_get_model(treeview);
-    selection = gtk_tree_view_get_selection(treeview);
-    selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
-    assigned_account = NULL;
-    first = TRUE;
-    is_selection = TRUE;    
-    DEBUG("Rows in selection = %i",
-          gtk_tree_selection_count_selected_rows(selection));
-    DEBUG("Entering loop over selection");
-
-    for (l = selected_rows; l != NULL; l = l->next)
-    {
-        DEBUG("passing first = %s",
-                                            first?"true":"false");
-        DEBUG("passing is_selection = %s",
-                                            is_selection?"true":"false");
-        DEBUG("passing path = %s",
-                       gtk_tree_path_to_string(l->data));
-        DEBUG("passing account value = %s",
-                    gnc_account_get_full_name(assigned_account));
-        gnc_gen_trans_assign_transfer_account(treeview,
-                       &first, &is_selection, l->data, &assigned_account, info);
-        DEBUG("returned value of account = %s", 
-                    gnc_account_get_full_name(assigned_account));
-        DEBUG("returned value of first = %s",first?"true":"false");
-        if (assigned_account == NULL) break;
-        gtk_tree_selection_unselect_path(selection, l->data);
+        break;
+    case GNCImport_CLEAR:
+    case GNCImport_UPDATE:
+        run_match_dialog (gui, trans_info);
+        break;
+    case GNCImport_SKIP:
+        /*The information displayed is only informative, until you select an action*/
+        break;
+    default:
+        PERR("I don't know what to do! (Yet...)");
+        break;
     }
-
-    g_list_free_full (selected_rows, (GDestroyNotify) gtk_tree_path_free);
-    g_list_free_full(l, (GDestroyNotify) gtk_tree_path_free);
-    LEAVE("");
-}
-
-static void
-gnc_gen_trans_row_activated_cb (GtkTreeView *treeview,
-                                GtkTreePath *path,
-                                GtkTreeViewColumn *column,
-                                GNCImportMainMatcher *info)
-{
-    Account *assigned_account;
-    gboolean first, is_selection;
-
-    ENTER("");
-    assigned_account = NULL;
-    first = TRUE;
-    is_selection = FALSE;
-    gnc_gen_trans_assign_transfer_account(treeview, 
-                            &first,  &is_selection, path,
-                            &assigned_account, info);
-    DEBUG("account returned = %s", gnc_account_get_full_name(assigned_account));
-    LEAVE("");
+    refresh_model_row(gui, model, &iter, trans_info);
 }
 
 static void
 gnc_gen_trans_row_changed_cb (GtkTreeSelection *selection,
-                              GNCImportMainMatcher *info)
+                              GNCImportMainMatcher *gui)
 {
     GtkTreeModel *model;
     GtkTreeIter iter;
-    GtkSelectionMode mode;
-
-    ENTER("");
-    mode = gtk_tree_selection_get_mode(selection);
-    switch (mode)
-    {
-        case GTK_SELECTION_MULTIPLE:
-            DEBUG("mode = GTK_SELECTION_MULTIPLE, no action");
-            break;
-        case GTK_SELECTION_NONE:
-            DEBUG("mode = GTK_SELECTION_NONE, no action");
-            break;
-        case GTK_SELECTION_BROWSE:
-            DEBUG("mode = GTK_SELECTION_BROWSE->default");
-        case GTK_SELECTION_SINGLE:
-            DEBUG("mode = GTK_SELECTION_SINGLE->default");
-        default:
-            DEBUG("mode = default unselect selected row");
-            if (gtk_tree_selection_get_selected(selection, &model, &iter))
-            {
-                gtk_tree_selection_unselect_iter(selection, &iter);
-            }
-    }
-    LEAVE("");
-}
 
-static void
-gnc_gen_trans_view_popup_menu (GtkTreeView *treeview, 
-                               GdkEvent *event,
-                               GNCImportMainMatcher *info)
-{    
-    GtkWidget *menu, *menuitem;
-    GdkEventButton *event_button;
-
-    ENTER ("");
-    menu = gtk_menu_new();
-    menuitem = gtk_menu_item_new_with_label(_("Assign a transfer account."));
-    g_signal_connect(menuitem, "activate",
-                     G_CALLBACK(
-                     gnc_gen_trans_assign_transfer_account_to_selection_cb),
-                     info);
-    DEBUG("Callback to assign destination account to selection connected");
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-    gtk_widget_show_all(menu);
-    event_button = (GdkEventButton *) event;
-    /* Note: event can be NULL here when called from view_onPopupMenu;
-     *  gdk_event_get_time() accepts a NULL argument */
-    gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 
-                    (event_button != NULL) ? event_button->button : 0, 
-                    gdk_event_get_time((GdkEvent*)event));
-    LEAVE ("");
-}
-
-static gboolean
-gnc_gen_trans_onButtonPressed_cb (GtkTreeView *treeview,
-                                  GdkEvent *event,
-                                  GNCImportMainMatcher *info)
-{
-    GdkEventButton *event_button;
-    ENTER("");
-    g_return_val_if_fail (treeview != NULL, FALSE);
-    g_return_val_if_fail (event != NULL, FALSE);
-    /* handle single click with the right mouse button? */
-    if (event->type == GDK_BUTTON_PRESS)
-    {
-        event_button = (GdkEventButton *) event;
-        if (event_button->button == GDK_BUTTON_SECONDARY)
-        {
-            DEBUG("Right mouseClick detected- popup the menu.");
-            gnc_gen_trans_view_popup_menu(treeview, event, info);
-            LEAVE("return TRUE");
-            return TRUE;
-        }
-    }
-    LEAVE("return FALSE");
-    return FALSE;
-}
-
-static gboolean
-gnc_gen_trans_onPopupMenu_cb (GtkTreeView *treeview,
-                              GdkEvent *event, 
-                              GNCImportMainMatcher *info)
-{
-    ENTER("");
-    /* respond to Shift-F10 popup menu hotkey */
-    gnc_gen_trans_view_popup_menu(treeview, NULL, info);
-    LEAVE ("");
-    return TRUE;
+    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
+        return;
+    gtk_tree_selection_unselect_iter(selection, &iter);
 }
 
-
 static GtkTreeViewColumn *
 add_text_column(GtkTreeView *view, const gchar *title, int col_num)
 {
@@ -739,11 +536,6 @@ gnc_gen_trans_init_view (GNCImportMainMatcher *info,
                      G_CALLBACK(gnc_gen_trans_row_activated_cb), info);
     g_signal_connect(selection, "changed",
                      G_CALLBACK(gnc_gen_trans_row_changed_cb), info);
-
-    g_signal_connect(view, "button-press-event", 
-                     G_CALLBACK(gnc_gen_trans_onButtonPressed_cb), info);
-    g_signal_connect(view, "popup-menu", 
-                     G_CALLBACK(gnc_gen_trans_onPopupMenu_cb), info);
 }
 
 static void
diff --git a/libgnucash/app-utils/fin.scm b/libgnucash/app-utils/fin.scm
index 4ffc3c1fa..a8edf0506 100644
--- a/libgnucash/app-utils/fin.scm
+++ b/libgnucash/app-utils/fin.scm
@@ -182,171 +182,3 @@
     )
   )
 )
-
-;; Further options to match what some (several? many?) lenders do (at
-;;  least in Canada):
-;; The posted interest rate is an annual rate that has a specified
-;;  compounding frequency per year (2 for mortgages in Canada).
-;; A payment frequency and amortization length are selected (e.g.
-;;  monthly payments for 25 years).
-;; The posted nominal rate is converted from the specified compounding
-;;  frequency to the equivalent rate at the payment frequency.
-;; The required payment is calculated.
-;; The payment is rounded up to the next dollar (or $10 dollars,
-;;  or whatever...)
-;; Each payment period, interest is calculated on the outstanding
-;;  balance.
-;; The interest is rounded to the nearest cent and added to the
-;;  balance.
-;; The payment is subtracted from the balance.
-;; The final payment will be smaller because all the other payments
-;;  were rounded up.
-;;
-;; For the purpose of creating scheduled transactions that properly
-;;  debit a source account while crediting the loan account and the
-;;  interest expense account, the first part (the calculation of the
-;;  required payment) doesn't really matter.  You have agreed
-;;  with the lender what the payment terms (interest rate, payment
-;;  frequency, payment amount) will be; you keep paying until the
-;;  balance is zero.
-;;
-;; To create the scheduled transactions, we need to build an
-;;  amortization table.
-;; If it weren't for the rounding of the interest to the nearest cent
-;;  each period, we could calculate the ith row of the amortization
-;;  table directly from the general annuity equation (as is done by
-;;  gnc:ipmt and gnc:ppmt).  But to deal with the intermediate
-;;  rounding, the amortization table has to be constructed iteratively
-;;  (as is done by the AMORT worksheet on the TI BA II Plus
-;;  financial calculator).
-;;
-;; =================================
-;; EXAMPLE:
-;; Say you borrow $100,000 at 5%/yr, compounded semi-annually.
-;; You amortize the loan over 2 years with 24 monthly payments.
-;; This calls for payments of $4,384.8418 at the end of each month.
-;; The lender rounds this up to $4,385.
-;;
-;; If you calculate the balance at each period directly using the annuity
-;; formula (like calc-principal does), and then use the those values to calculate
-;; the principal and interest paid, the first 10 rows of the amortization table
-;; look like this (the values are rounded to the nearest cent for _display_, but
-;; not for calculating the next period):
-;;
-;; PERIOD | Open       | Interest | Principal | End
-;;    1   |$100,000.00 |  $412.39 | $3,972.61 | $96,027.39
-;;    2   | $96,027.39 |  $396.01 | $3,988.99 | $92,038.40 
-;;    3   | $92,038.40 |  $379.56 | $4,005.44 | $88,032.96 
-;;    4   | $88,032.96 |  $363.04 | $4,021.96 | $84,011.00 
-;;    5   | $84,011.00 |  $346.45 | $4,038.55 | $79,972.45 
-;;    6   | $79,972.45 |  $329.80 | $4,055.20 | $75,917.25 
-;;    7   | $75,917.25 |  $313.08 | $4,071.92 | $71,845.33 
-;;    8   | $71,845.33 |  $296.28 | $4,088.72 | $67,756.61 
-;;    9   | $67,756.61 |  $279.43 | $4,105.57 | $63,651.04 
-;;   10   | $63,651.04 |  $262.49 | $4,122.51 | $59,528.53
-;;
-;; If you calculate each period sequentially (rounding the interest and balance
-;; at each step), you get:
-;;
-;; PERIOD | Open       | Interest | Principal | End
-;;    1   |$100,000.00 |  $412.39 | $3,972.61 | $96,027.39
-;;    2   | $96,027.39 |  $396.01 | $3,988.99 | $92,038.40 
-;;    3   | $92,038.40 |  $379.56 | $4,005.44 | $88,032.96 
-;;    4   | $88,032.96 |  $363.04 | $4,021.96 | $84,011.00 
-;;    5   | $84,011.00 |  $346.45 | $4,038.55 | $79,972.45 
-;;    6   | $79,972.45 |  $329.80 | $4,055.20 | $75,917.25 
-;;    7   | $75,917.25 |  $313.08 | $4,071.92 | $71,845.33 
-;;    8   | $71,845.33 |  $296.28 | $4,088.72 | $67,756.61 
-;;    9   | $67,756.61 |  $279.42 | $4,105.58 | $63,651.03 <- Different 
-;;   10   | $63,651.03 |  $262.49 | $4,122.51 | $59,528.52 <- still $0.01 off
-;;
-;; =================================
-;;
-;; For the following functions the argument names are:
-;;  py: payment frequency (number of payments per year)
-;;  cy: compounding frequency of the nominal rate (per year)
-;;  iy: nominal annual interest rate
-;;  pv: the present value (opening balance)
-;;  pmt: the size of the periodic payment
-;;  n: the payment period we are asking about (the first payment is n=1)
-;;  places: number of decimal places to round the interest amount to 
-;;          at each payment (999 does no rounding)
-;;
-;; Note: only ordinary annuities are supported (payments at the end of
-;;  each period, not at the beginning of each period)
-;;
-;; Unlike the AMORT worksheet on the BA II Plus, these methods will
-;;  handle the smaller payment (bringing the balance to zero, then
-;;  zeroing future payments)
-;;
-;; The present value (pv) must be non-negative.  If not, the balance will be
-;;  treated as 0.
-;; The payment (pmt) can be positive (paying interest, and hopefully
-;;  reducing the balance each payment), or negative (increasing the balance
-;   each payment).
-;; The payment number (n) must be positive for amort_pmt, amort_ppmt, and
-;;  amort_ipmt.  I.e., the first payment is payment 1.
-;; The payment number (n) must be non-negative for amort_balance.  (In this
-;;  case, payment zero is at the _beginning_ of the first period, so
-;;  amort_balance will just be the initial balance.)
-;; If the above conditions on n are violated, the functions return -1 (#f is
-;;  not used, because it causes gnucash to crash).
-;;
-;; A negative interest rate works (if you can find a lender who charges
-;;  negative rates), but negative compounding frequency, or negative payment
-;;  frequency is a bad idea.
-
-;; Calculate the balance remaining after the nth payment
-;; (n must be greater than or equal to zero)
-(define (gnc:amort_pmt py cy iy pv pmt n places)
-  (if (< n 1) -1 ;; Returning #f here causes gnucash to crash on startup
-    (let* ((prevBal (gnc:amort_balance py cy iy pv pmt (- n 1) places))
-           (balBeforePayment
-		     (amort_balanceAfterInterest prevBal py cy iy places))
-           (balAfterPayment (amort_balanceAfterPayment balBeforePayment pmt)))
-      (- balBeforePayment balAfterPayment))))
-
-;; Calculate the amount of the nth payment that is principal
-;; (n must be greater than zero)
-(define (gnc:amort_ppmt py cy iy pv pmt n places)
-  (if (< n 1) -1
-    (let* ((prevBal (gnc:amort_balance py cy iy pv pmt (- n 1) places))
-	       (bal-after-int (amort_balanceAfterInterest prevBal py cy iy places))
-           (newBal (amort_balanceAfterPayment bal-after-int pmt)))
-      (- prevBal newBal))))
-
-;; Calculate the amount of the nth payment that is interest
-;; (n must be greater than zero)
-(define (gnc:amort_ipmt py cy iy pv pmt n places)
-  (if (< n 1) -1
-    (let* ((prevBal(gnc:amort_balance py cy iy pv pmt (- n 1) places)))
-      (amort_interest prevBal py cy iy places))))
-
-;; "Private" helper functions:
-
-;; Calculate the amount of interest on the current balance,
-;; rounded to the specified number of decimal places
-(define (amort_interest balance py cy iy places)
-  (roundToPlaces (* balance (gnc:periodic_rate iy py cy)) places)
-)
-
-;; Calculate the new balance after applying the interest, but before
-;; applying the payment
-(define (amort_balanceAfterInterest prevBalance py cy iy places)
-  (+ prevBalance (amort_interest prevBalance py cy iy places))
-)
-
-;; Apply the payment to the balance (after the interest has been
-;; added), without letting the balance go below zero.
-(define (amort_balanceAfterPayment balanceBeforePmt pmt)
-  (max 0 (- balanceBeforePmt pmt))
-)
-
-;; Round the value to the specified number of decimal places.
-;; 999 places means no rounding (#f is not used, because only numbers can be
-;; entered in the scheduled transaction editor)
-(define (roundToPlaces value places)
-  (if (= places 999) value
-    (/ (round (* value (expt 10 places))) (expt 10 places))
-  )
-)



Summary of changes:
 CMakeLists.txt                              |   4 +-
 gnucash/gtkbuilder/dialog-import.glade      |  29 +--
 gnucash/import-export/import-main-matcher.c | 270 ++++------------------------
 3 files changed, 36 insertions(+), 267 deletions(-)



More information about the gnucash-changes mailing list