/* HomeBank -- Free, easy, personal accounting for everyone. * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * * HomeBank is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * HomeBank is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "homebank.h" #include "hb-hbfile.h" #include "hb-archive.h" #include "hb-transaction.h" /****************************************************************************/ /* Debug macros */ /****************************************************************************/ #define MYDEBUG 0 #if MYDEBUG #define DB(x) (x); #else #define DB(x); #endif /* our global datas */ extern struct HomeBank *GLOBALS; extern struct Preferences *PREFS; /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/ gboolean hbfile_file_hasbackup(gchar *filepath) { gchar *bakfilepath; bakfilepath = hb_util_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb~"); GLOBALS->xhb_hasbak = g_file_test(bakfilepath, G_FILE_TEST_EXISTS); g_free(bakfilepath); //todo check here if need to return something return GLOBALS->xhb_hasbak; } /* static gint hbfile_file_load_xhb(gchar *filepath) { } static void hbfile_file_load_backup_xhb(void) { //todo: get from dialog.c, and split between dilaog.c/hbfile.c } */ void hbfile_replace_basecurrency(Currency4217 *curfmt) { Currency *item; guint32 oldkcur; DB( g_print("\n[hbfile] replace base currency \n") ); oldkcur = GLOBALS->kcur; da_cur_remove(oldkcur); item = currency_add_from_user(curfmt); GLOBALS->kcur = item->key; DB( g_print(" %d ==> %d %s\n", oldkcur, GLOBALS->kcur, item->iso_code) ); } void hbfile_change_basecurrency(guint32 key) { GList *list; guint32 oldkcur; // set every rate to 0 list = g_hash_table_get_values(GLOBALS->h_cur); while (list != NULL) { Currency *entry = list->data; if(entry->key != GLOBALS->kcur) { entry->rate = 0.0; entry->mdate = 0; } list = g_list_next(list); } g_list_free(list); oldkcur = GLOBALS->kcur; GLOBALS->kcur = key; // update account with old base currency list = g_hash_table_get_values(GLOBALS->h_acc); while (list != NULL) { Account *acc = list->data; if( acc->kcur == oldkcur ) acc->kcur = key; list = g_list_next(list); } g_list_free(list); GLOBALS->changes_count++; } GList *hbfile_transaction_get_all(guint32 kacc) { GList *lst_acc, *lnk_acc; GList *lnk_txn; GList *list; list = NULL; lst_acc = g_hash_table_get_values(GLOBALS->h_acc); lnk_acc = g_list_first(lst_acc); while (lnk_acc != NULL) { Account *acc = lnk_acc->data; if( (acc->flags & (AF_CLOSED|AF_NOREPORT)) ) goto next_acc; if( (kacc > 0 ) && (acc->key != kacc) ) goto next_acc; lnk_txn = g_queue_peek_head_link(acc->txn_queue); while (lnk_txn != NULL) { list = g_list_append(list, lnk_txn->data); lnk_txn = g_list_next(lnk_txn); } next_acc: lnk_acc = g_list_next(lnk_acc); } g_list_free(lst_acc); return da_transaction_sort (list); } GQueue *hbfile_transaction_get_partial(guint32 minjulian, guint32 maxjulian) { GList *lst_acc, *lnk_acc; GList *lnk_txn; GQueue *txn_queue; txn_queue = g_queue_new (); lst_acc = g_hash_table_get_values(GLOBALS->h_acc); lnk_acc = g_list_first(lst_acc); while (lnk_acc != NULL) { Account *acc = lnk_acc->data; if( (acc->flags & (AF_CLOSED|AF_NOREPORT)) ) goto next_acc; lnk_txn = g_queue_peek_tail_link(acc->txn_queue); while (lnk_txn != NULL) { Transaction *txn = lnk_txn->data; if( txn->date < minjulian ) //no need to go below mindate break; if( !(txn->status == TXN_STATUS_REMIND) && (txn->date >= minjulian) && (txn->date <= maxjulian) ) { g_queue_push_head (txn_queue, txn); } lnk_txn = g_list_previous(lnk_txn); } next_acc: lnk_acc = g_list_next(lnk_acc); } g_list_free(lst_acc); return txn_queue; } void hbfile_sanity_check(void) { GList *lst_acc, *lnk_acc; GList *lnk_txn; GList *lxxx, *list; DB( g_print("\n[hbfile] !! sanity_check !! \n") ); DB( g_print(" - transaction\n") ); lst_acc = g_hash_table_get_values(GLOBALS->h_acc); lnk_acc = g_list_first(lst_acc); while (lnk_acc != NULL) { Account *acc = lnk_acc->data; lnk_txn = g_queue_peek_head_link(acc->txn_queue); while (lnk_txn != NULL) { Transaction *txn = lnk_txn->data; da_transaction_consistency(txn); lnk_txn = g_list_next(lnk_txn); } lnk_acc = g_list_next(lnk_acc); } g_list_free(lst_acc); DB( g_print(" - scheduled/template\n") ); list = g_list_first(GLOBALS->arc_list); while (list != NULL) { Archive *entry = list->data; da_archive_consistency(entry); list = g_list_next(list); } DB( g_print(" - account\n") ); lxxx = list = g_hash_table_get_values(GLOBALS->h_acc); while (list != NULL) { Account *item = list->data; da_acc_consistency(item); list = g_list_next(list); } g_list_free(lxxx); DB( g_print(" - payee\n") ); lxxx = list = g_hash_table_get_values(GLOBALS->h_pay); while (list != NULL) { Payee *item = list->data; da_pay_consistency(item); list = g_list_next(list); } g_list_free(lxxx); DB( g_print(" - category\n") ); lxxx = list = g_hash_table_get_values(GLOBALS->h_cat); while (list != NULL) { Category *item = list->data; da_cat_consistency(item); list = g_list_next(list); } g_list_free(lxxx); } void hbfile_anonymize(void) { GList *lst_acc, *lnk_acc; GList *lnk_txn; GList *lxxx, *list; guint cnt, i; DB( g_print("\n[hbfile] anonymize\n") ); // owner hbfile_change_owner(g_strdup("An0nym0us")); GLOBALS->changes_count++; GLOBALS->hbfile_is_new = TRUE; // filename hbfile_change_filepath(g_build_filename(PREFS->path_hbfile, "anonymized.xhb", NULL)); // accounts lxxx = list = g_hash_table_get_values(GLOBALS->h_acc); while (list != NULL) { Account *item = list->data; g_free(item->name); item->name = g_strdup_printf("account %d", item->key); g_free(item->number); item->number = NULL; g_free(item->bankname); item->bankname = NULL; GLOBALS->changes_count++; list = g_list_next(list); } g_list_free(lxxx); //payees lxxx = list = g_hash_table_get_values(GLOBALS->h_pay); while (list != NULL) { Payee *item = list->data; if(item->key != 0) { g_free(item->name); item->name = g_strdup_printf("payee %d", item->key); GLOBALS->changes_count++; } list = g_list_next(list); } g_list_free(lxxx); //categories lxxx = list = g_hash_table_get_values(GLOBALS->h_cat); while (list != NULL) { Category *item = list->data; if(item->key != 0) { g_free(item->name); item->name = g_strdup_printf("category %d", item->key); GLOBALS->changes_count++; } list = g_list_next(list); } g_list_free(lxxx); //tags lxxx = list = g_hash_table_get_values(GLOBALS->h_tag); while (list != NULL) { Tag *item = list->data; if(item->key != 0) { g_free(item->name); item->name = g_strdup_printf("tag %d", item->key); GLOBALS->changes_count++; } list = g_list_next(list); } g_list_free(lxxx); //assigns lxxx = list = g_hash_table_get_values(GLOBALS->h_rul); while (list != NULL) { Assign *item = list->data; if(item->key != 0) { g_free(item->text); item->text = g_strdup_printf("assign %d", item->key); GLOBALS->changes_count++; } list = g_list_next(list); } g_list_free(lxxx); //archives cnt = 0; list = g_list_first(GLOBALS->arc_list); while (list != NULL) { Archive *item = list->data; g_free(item->wording); item->wording = g_strdup_printf("archive %d", cnt++); GLOBALS->changes_count++; //later split anonymize also list = g_list_next(list); } //transaction lst_acc = g_hash_table_get_values(GLOBALS->h_acc); lnk_acc = g_list_first(lst_acc); while (lnk_acc != NULL) { Account *acc = lnk_acc->data; lnk_txn = g_queue_peek_head_link(acc->txn_queue); while (lnk_txn != NULL) { Transaction *item = lnk_txn->data; Split *split; g_free(item->info); item->info = NULL; g_free(item->wording); item->wording = g_strdup_printf("memo %d", item->date); GLOBALS->changes_count++; if(item->flags & OF_SPLIT) { for(i=0;isplits[i]; if( split == NULL ) break; if(split->memo != NULL) g_free(split->memo); split->memo = g_strdup_printf("memo %d", i); GLOBALS->changes_count++; } } lnk_txn = g_list_next(lnk_txn); } lnk_acc = g_list_next(lnk_acc); } g_list_free(lst_acc); } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/ void hbfile_change_owner(gchar *owner) { g_free(GLOBALS->owner); GLOBALS->owner = (owner != NULL) ? owner : NULL; } void hbfile_change_filepath(gchar *filepath) { g_free(GLOBALS->xhb_filepath); GLOBALS->xhb_filepath = (filepath != NULL) ? filepath : NULL; } void hbfile_cleanup(gboolean file_clear) { Transaction *txn; DB( g_print("\n[hbfile] cleanup\n") ); DB( g_print("- file clear is %d\n", file_clear) ); // Free data storage txn = g_trash_stack_pop(&GLOBALS->txn_stk); while( txn != NULL ) { da_transaction_free (txn); txn = g_trash_stack_pop(&GLOBALS->txn_stk); } da_transaction_destroy(); da_archive_destroy(GLOBALS->arc_list); g_hash_table_destroy(GLOBALS->h_memo); da_asg_destroy(); da_tag_destroy(); da_cat_destroy(); da_pay_destroy(); da_acc_destroy(); da_cur_destroy(); hbfile_change_owner(NULL); if(file_clear) hbfile_change_filepath(NULL); } void hbfile_setup(gboolean file_clear) { DB( g_print("\n[hbfile] setup\n") ); DB( g_print("- file clear is %d\n", file_clear) ); // Allocate data storage da_cur_new(); da_acc_new(); da_pay_new(); da_cat_new(); da_tag_new(); da_asg_new(); GLOBALS->h_memo = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)g_free, NULL); GLOBALS->arc_list = NULL; GLOBALS->txn_stk = NULL; if(file_clear == TRUE) { //todo: maybe translate this also hbfile_change_filepath(g_build_filename(PREFS->path_hbfile, "untitled.xhb", NULL)); GLOBALS->hbfile_is_new = TRUE; DB( g_print("- path_hbfile is '%s'\n", PREFS->path_hbfile) ); DB( g_print("- xhb_filepath is '%s'\n", GLOBALS->xhb_filepath) ); } else { GLOBALS->hbfile_is_new = FALSE; } hbfile_change_owner(g_strdup(_("Unknown"))); GLOBALS->kcur = 1; GLOBALS->vehicle_category = 0; GLOBALS->auto_smode = 1; GLOBALS->auto_nbdays = 0; GLOBALS->auto_weekday = 1; GLOBALS->changes_count = 0; GLOBALS->xhb_hasbak = FALSE; }