diff --git a/CMakeLists.txt b/CMakeLists.txt index 903ebcc5df..23eb5e9ed0 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 fd8935b5ac..59ed257be9 100644 --- a/gnucash/gtkbuilder/dialog-import.glade +++ b/gnucash/gtkbuilder/dialog-import.glade @@ -14,9 +14,6 @@ 600 dialog - - - True @@ -168,6 +165,7 @@ 10 + False False Choose a format False @@ -175,9 +173,6 @@ 600 400 dialog - - - True @@ -306,9 +301,6 @@ True False Preferences - - - True @@ -562,9 +554,6 @@ 600 400 dialog - - - True @@ -728,8 +717,7 @@ This transaction requires your intervention or it will NOT be imported. - 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. + Double click on the transaction to change the matching transaction to reconcile, or the destination account of the auto-balance split (if required). False @@ -738,9 +726,6 @@ Multiply select rows using Ctrl-Click, Shift-Click and Rubber banding . Right-Cl False dialog - - - True @@ -779,7 +764,6 @@ Multiply select rows using Ctrl-Click, Shift-Click and Rubber banding . Right-Cl True False - 42 6 12 @@ -1006,7 +990,6 @@ Multiply select rows using Ctrl-Click, Shift-Click and Rubber banding . Right-Cl True True - 2 5 5 False @@ -1124,11 +1107,8 @@ Multiply select rows using Ctrl-Click, Shift-Click and Rubber banding . Right-Cl True True False - True - - multiple - + @@ -1165,9 +1145,6 @@ Multiply select rows using Ctrl-Click, Shift-Click and Rubber banding . Right-Cl 400 dialog - - - True diff --git a/gnucash/import-export/import-main-matcher.c b/gnucash/import-export/import-main-matcher.c index 7172c52e27..7734296022 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 4ffc3c1faa..a8edf0506c 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)) - ) -)