From fab6bbc56a2ac36603a6c8f16698fa2e8fd884a7 Mon Sep 17 00:00:00 2001 From: Dave Peticolas Date: Thu, 22 Feb 2001 06:09:50 +0000 Subject: [PATCH] Bill Gribble's qif importing patches. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3674 57a11ea4-9604-0410-9ed3-97b8803252fd --- ChangeLog | 8 ++ src/engine/gnc-commodity.c | 2 +- src/gnome/druid-qif-import.c | 78 +++++++++++------ src/scm/qif-import/qif-dialog-utils.scm | 106 ++++++++++++------------ src/scm/qif-import/qif-guess-map.scm | 75 +++++++++++++---- src/scm/qif-import/qif-parse.scm | 5 +- src/scm/qif-import/qif-to-gnc.scm | 25 ++++-- 7 files changed, 192 insertions(+), 107 deletions(-) diff --git a/ChangeLog b/ChangeLog index cafecda4a3..9d634d269f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2001-02-15 Bill Gribble + + * src/scm/qif-import/qif-guess-map.scm: add stock hash + save/restore to map IO + + * src/scm/qif-import/qif-to-gnc.scm: bug fixes to remove duplicate + account problems + 2001-02-15 Christian Stimming * src/scm/report-utilities.scm: Added functions to filter accounts diff --git a/src/engine/gnc-commodity.c b/src/engine/gnc-commodity.c index 229c3e4419..442891a373 100644 --- a/src/engine/gnc-commodity.c +++ b/src/engine/gnc-commodity.c @@ -499,7 +499,7 @@ gnc_commodity_table_add_namespace(gnc_commodity_table * table, ********************************************************************/ static int -ns_helper(gpointer key, gpointer value, gpointer user_data) { +ns_helper(gpointer key, gpoin4er value, gpointer user_data) { gnc_commodity * c = value; gnc_commodity_destroy(c); g_free(key); diff --git a/src/gnome/druid-qif-import.c b/src/gnome/druid-qif-import.c index 634796e561..60e853d572 100644 --- a/src/gnome/druid-qif-import.c +++ b/src/gnome/druid-qif-import.c @@ -86,6 +86,7 @@ struct _qifimportwindow { SCM gnc_acct_info; SCM stock_hash; + SCM new_stocks; SCM imported_account_group; SCM match_transactions; @@ -167,6 +168,7 @@ gnc_ui_qif_import_druid_make(void) { retval->memo_display_info = SCM_BOOL_F; retval->memo_map_info = SCM_BOOL_F; retval->stock_hash = SCM_BOOL_F; + retval->new_stocks = SCM_BOOL_F; retval->imported_account_group = SCM_BOOL_F; retval->match_transactions = SCM_BOOL_F; retval->selected_transaction = 0; @@ -223,6 +225,7 @@ gnc_ui_qif_import_druid_make(void) { retval->acct_map_info = gh_list_ref(mapping_info, gh_int2scm(1)); retval->cat_map_info = gh_list_ref(mapping_info, gh_int2scm(2)); retval->memo_map_info = gh_list_ref(mapping_info, gh_int2scm(3)); + retval->stock_hash = gh_list_ref(mapping_info, gh_int2scm(4)); scm_protect_object(retval->imported_files); scm_protect_object(retval->selected_file); @@ -234,6 +237,7 @@ gnc_ui_qif_import_druid_make(void) { scm_protect_object(retval->acct_display_info); scm_protect_object(retval->acct_map_info); scm_protect_object(retval->stock_hash); + scm_protect_object(retval->new_stocks); scm_protect_object(retval->imported_account_group); scm_protect_object(retval->match_transactions); @@ -278,6 +282,7 @@ gnc_ui_qif_import_druid_destroy (QIFImportWindow * window) { scm_unprotect_object(window->acct_display_info); scm_unprotect_object(window->acct_map_info); scm_unprotect_object(window->stock_hash); + scm_unprotect_object(window->new_stocks); scm_unprotect_object(window->imported_account_group); scm_unprotect_object(window->match_transactions); @@ -1283,7 +1288,6 @@ gnc_ui_qif_import_convert(QIFImportWindow * wind) { /* get the default currency */ char * currname = gtk_entry_get_text(GTK_ENTRY(wind->currency_entry)); - /* busy cursor */ gnc_suspend_gui_refresh (); gnc_set_busy_cursor(NULL); @@ -1340,7 +1344,7 @@ gnc_ui_qif_import_convert(QIFImportWindow * wind) { scm_unprotect_object(wind->match_transactions); wind->match_transactions = retval; scm_protect_object(wind->match_transactions); - + /* skip to the last page if we couldn't find duplicates * in the new group */ if((retval == SCM_BOOL_F) || @@ -1402,10 +1406,11 @@ gnc_ui_qif_import_memo_next_cb(GnomeDruidPage * page, QIFImportWindow * wind = gtk_object_get_data(GTK_OBJECT(user_data), "qif_window_struct"); - SCM any_new = gh_eval_str("qif-import:any-new-accts?"); - SCM any_stock = gh_eval_str("qif-import:any-new-stock-accts?"); - int show_matches; + SCM any_new = gh_eval_str("qif-import:any-new-accts?"); + SCM update_stock = gh_eval_str("qif-import:update-stock-hash"); + int show_matches; + /* if any accounts are new, ask about the currency; else, * just skip that page */ if((gh_call1(any_new, wind->acct_map_info) == SCM_BOOL_T) || @@ -1416,7 +1421,12 @@ gnc_ui_qif_import_memo_next_cb(GnomeDruidPage * page, else { /* if we need to look at stocks, do that, otherwise import * xtns and go to the duplicates page */ - if(gh_call1(any_stock, wind->acct_map_info) == SCM_BOOL_T) { + scm_unprotect_object(wind->new_stocks); + wind->new_stocks = gh_call2(update_stock, wind->stock_hash, + wind->acct_map_info); + scm_protect_object(wind->new_stocks); + + if(wind->new_stocks != SCM_BOOL_F) { if(wind->show_doc_pages) { gnome_druid_set_page(GNOME_DRUID(wind->druid), get_named_page(wind, "commodity_doc_page")); @@ -1463,10 +1473,15 @@ gnc_ui_qif_import_currency_next_cb(GnomeDruidPage * page, gpointer user_data) { QIFImportWindow * wind = gtk_object_get_data(GTK_OBJECT(user_data), "qif_window_struct"); - SCM any_stock = gh_eval_str("qif-import:any-new-stock-accts?"); + SCM update_stock = gh_eval_str("qif-import:update-stock-hash"); int show_matches; - if(gh_call1(any_stock, wind->acct_map_info) == SCM_BOOL_T) { + scm_unprotect_object(wind->new_stocks); + wind->new_stocks = gh_call2(update_stock, wind->stock_hash, + wind->acct_map_info); + scm_protect_object(wind->new_stocks); + + if(wind->new_stocks != SCM_BOOL_F) { if(wind->show_doc_pages) { gnome_druid_set_page(GNOME_DRUID(wind->druid), get_named_page(wind, "commodity_doc_page")); @@ -1569,10 +1584,9 @@ gnc_ui_qif_import_commodity_prepare_cb(GnomeDruidPage * page, gtk_object_get_data(GTK_OBJECT(user_data), "qif_window_struct"); SCM hash_ref = gh_eval_str("hash-ref"); - SCM setup_stock_hash = gh_eval_str("qif-import:setup-stock-hash"); - SCM setup_info; - SCM stock_names; + SCM stocks; SCM comm_ptr_token; + SCM show_matches; gnc_commodity * commodity; GnomeDruidPage * back_page = get_named_page(wind, "commodity_doc_page"); @@ -1580,18 +1594,33 @@ gnc_ui_qif_import_commodity_prepare_cb(GnomeDruidPage * page, /* only set up once */ if(wind->commodity_pages) return; - - /* make a list of the new stocks that we need info about */ - setup_info = gh_call1(setup_stock_hash, wind->acct_map_info); - stock_names = gh_cadr(setup_info); - - scm_unprotect_object(wind->stock_hash); - wind->stock_hash = gh_car(setup_info); - scm_protect_object(wind->stock_hash); + /* this shouldn't happen, but DTRT if it does */ + if(gh_null_p(wind->new_stocks)) { + printf("somehow got to commodity doc page with nothing to do... BUG!\n"); + show_matches = gnc_ui_qif_import_convert(wind); + + if(show_matches) { + if(wind->show_doc_pages) { + /* check for matches .. the docpage does it automatically */ + gnome_druid_set_page(GNOME_DRUID(wind->druid), + get_named_page(wind, "match_doc_page")); + } + else { + gnome_druid_set_page(GNOME_DRUID(wind->druid), + get_named_page(wind, "match_duplicates_page")); + } + } + else { + gnome_druid_set_page(GNOME_DRUID(wind->druid), + get_named_page(wind, "end_page")); + } + } + /* insert new pages, one for each stock */ - while(!gh_null_p(stock_names)) { - comm_ptr_token = gh_call2(hash_ref, wind->stock_hash, gh_car(stock_names)); + stocks = wind->new_stocks; + while(!gh_null_p(stocks)) { + comm_ptr_token = gh_call2(hash_ref, wind->stock_hash, gh_car(stocks)); commodity = gw_wcp_get_ptr(comm_ptr_token); new_page = make_qif_druid_page(commodity); @@ -1608,7 +1637,7 @@ gnc_ui_qif_import_commodity_prepare_cb(GnomeDruidPage * page, GNOME_DRUID_PAGE(new_page->page)); back_page = GNOME_DRUID_PAGE(new_page->page); - stock_names = gh_cdr(stock_names); + stocks = gh_cdr(stocks); gtk_widget_show_all(new_page->page); } } @@ -1833,8 +1862,9 @@ gnc_ui_qif_import_finish_cb(GnomeDruidPage * gpage, gnc_resume_gui_refresh(); /* write out mapping info before destroying the window */ - gh_call3(save_map_prefs, wind->acct_map_info, wind->cat_map_info, - wind->memo_map_info); + gh_apply(save_map_prefs, + SCM_LIST4(wind->acct_map_info, wind->cat_map_info, + wind->memo_map_info, wind->stock_hash)); gnc_ui_qif_import_druid_destroy(wind); } diff --git a/src/scm/qif-import/qif-dialog-utils.scm b/src/scm/qif-import/qif-dialog-utils.scm index 6d76511561..7c53ac4eb3 100644 --- a/src/scm/qif-import/qif-dialog-utils.scm +++ b/src/scm/qif-import/qif-dialog-utils.scm @@ -544,25 +544,6 @@ (vector->list hash-table)) retval)) -(define (qif-import:any-new-stock-accts? hash-table) - (let ((retval #f)) - (for-each - (lambda (bin) - (for-each - (lambda (elt) - (if (and - (qif-map-entry:new-acct? (cdr elt)) - (qif-map-entry:display? (cdr elt)) - (or - (memv GNC-STOCK-TYPE - (qif-map-entry:allowed-types (cdr elt))) - (memv GNC-MUTUAL-TYPE - (qif-map-entry:allowed-types (cdr elt))))) - (set! retval #t))) - bin)) - (vector->list hash-table)) - retval)) - (define (qif-import:fix-from-acct qif-file new-acct-name) (for-each (lambda (xtn) @@ -589,42 +570,59 @@ (match:substring match 2)))) fullname))) -(define (qif-import:setup-stock-hash hash-table) - (let ((newhash (make-hash-table 20)) - (names '())) - (for-each - (lambda (bin) - (for-each - (lambda (elt) - (if (and - (qif-map-entry:new-acct? (cdr elt)) - (qif-map-entry:display? (cdr elt)) - (or - (memv GNC-STOCK-TYPE - (qif-map-entry:allowed-types (cdr elt))) - (memv GNC-MUTUAL-TYPE - (qif-map-entry:allowed-types (cdr elt))))) - (let* ((name (qif-map-entry:qif-name (cdr elt))) - (stock-name (qif-import:get-account-name name))) - (if (not stock-name) - (begin - (display "stock-name #f.. name ==") - (display name)(newline))) - - (if (not (hash-ref newhash stock-name)) - (begin - (set! names (cons stock-name names)) - (hash-set! newhash stock-name - (gnc:commodity-create - stock-name - GNC_COMMODITY_NS_NYSE - stock-name - "" - 100000))))))) - bin)) - (vector->list hash-table)) - (list newhash (sort names stringlist hashtab)) + (hash-fold + (lambda (key value p) + (set! table (cons (cons key (simple-obj-to-list value)) table)) + #f) #f hashtab) (write table))) (define (qif-import:read-map tablist) @@ -143,7 +149,36 @@ tablist) table)) -(define (qif-import:save-map-prefs acct-map cat-map memo-map) +(define (qif-import:read-commodities commlist) + (let ((table (make-hash-table 20))) + (for-each + (lambda (entry) + (if (and (list? entry) + (= 3 (length entry))) + (let ((name (car entry)) + (namespace (cadr entry)) + (mnemonic (caddr entry))) + (hash-set! table name + (gnc:commodity-table-lookup (gnc:engine-commodities) + namespace mnemonic))))) + commlist) + table)) + +(define (qif-import:write-commodities hashtab) + (let ((table '())) + (hash-fold + (lambda (key value p) + (if (gw:wcp-is-of-type? value) + (set! table + (cons (list key + (gnc:commodity-get-namespace value) + (gnc:commodity-get-mnemonic value)) + table))) + #f) #f hashtab) + (write table))) + + +(define (qif-import:save-map-prefs acct-map cat-map memo-map stock-map) (let* ((pref-dir (build-path (getenv "HOME") ".gnucash")) (pref-filename (build-path pref-dir "qif-accounts-map")) (save-ok #f)) @@ -168,12 +203,18 @@ (display ";;; map from QIF accounts to GNC accounts") (newline) (qif-import:write-map acct-map) - + (newline) + (display ";;; map from QIF categories to GNC accounts") (newline) (qif-import:write-map cat-map) - + (newline) + (display ";;; map from QIF payee/memo to GNC accounts") (newline) (qif-import:write-map memo-map) + (newline) + + (display ";;; map from QIF stock name to GNC commodity") (newline) + (qif-import:write-commodities stock-map) (newline)))))) diff --git a/src/scm/qif-import/qif-parse.scm b/src/scm/qif-import/qif-parse.scm index 534318df4e..3c9ec80d29 100644 --- a/src/scm/qif-import/qif-parse.scm +++ b/src/scm/qif-import/qif-parse.scm @@ -154,12 +154,11 @@ ((string=? mangled-string "invst") ;; these are brokerage accounts. (list GNC-BANK-TYPE)) ((string=? mangled-string "oth a") - (list GNC-ASSET-TYPE GNC-BANK-TYPE GNC-CASH-TYPE GNC-STOCK-TYPE - GNC-MUTUAL-TYPE)) + (list GNC-ASSET-TYPE GNC-BANK-TYPE GNC-CASH-TYPE)) ((string=? mangled-string "oth l") (list GNC-LIABILITY-TYPE GNC-CCARD-TYPE)) ((string=? mangled-string "mutual") - (list GNC-MUTUAL-TYPE GNC-STOCK-TYPE)) + (list GNC-BANK-TYPE)) (#t (display "qif-parse:parse-acct-type : unhandled account type ") (display read-value) diff --git a/src/scm/qif-import/qif-to-gnc.scm b/src/scm/qif-import/qif-to-gnc.scm index f1aabbcfee..ee05ab82f7 100644 --- a/src/scm/qif-import/qif-to-gnc.scm +++ b/src/scm/qif-import/qif-to-gnc.scm @@ -41,19 +41,28 @@ (string-append short-name (sprintf #f " %a" count))))) short-name)) + (define (compatible? account) + (let ((acc-type (gnc:account-get-type account)) + (acc-currency (gnc:account-get-currency account)) + (acc-security (gnc:account-get-security account))) + (if (memv acc-type + (list GNC-STOCK-TYPE GNC-MUTUAL-TYPE)) + (and + (list? allowed-types) + (memv acc-type allowed-types) + (gnc:commodity-equiv? acc-currency currency) + (gnc:commodity-equiv? acc-security security)) + (and + (list? allowed-types) + (memv acc-type allowed-types) + (gnc:commodity-equiv? acc-currency currency))))) + ;; just because we found an account doesn't mean we can use it. ;; if the name is in use but the currency, security, or type are ;; incompatible, we need to create a new account with a modified ;; name. (if same-gnc-account - (if (and (gnc:commodity-equiv? - currency (gnc:account-get-currency same-gnc-account)) - (or (eq? (gnc:account-get-security same-gnc-account) #f) - (gnc:commodity-equiv? - security (gnc:account-get-security same-gnc-account))) - (list? allowed-types) - (memv (gnc:account-get-type same-gnc-account) - allowed-types)) + (if (compatible? same-gnc-account) (begin ;; everything is ok, so we can just use the same ;; account. Make sure we make the same type.