/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2014 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
extern struct HomeBank *GLOBALS;
-
-
-
-Account *
-da_acc_clone(Account *src_item)
-{
-Account *new_item = g_memdup(src_item, sizeof(Account));
-
- DB( g_print("da_acc_clone\n") );
- if(new_item)
- {
- //duplicate the string
- new_item->name = g_strdup(src_item->name);
- new_item->number = g_strdup(src_item->number);
- new_item->bankname = g_strdup(src_item->bankname);
- }
- return new_item;
-}
-
-
void
da_acc_free(Account *item)
{
{
DB( g_print(" => %d, %s\n", item->key, item->name) );
- g_free(item->imp_name);
g_free(item->name);
g_free(item->number);
g_free(item->bankname);
+ g_free(item->notes);
+
+ g_queue_free (item->txn_queue);
+
g_free(item);
}
}
Account *
da_acc_malloc(void)
{
+Account *item;
+
DB( g_print("da_acc_malloc\n") );
- return g_malloc0(sizeof(Account));
+ item = g_malloc0(sizeof(Account));
+ item->kcur = GLOBALS->kcur;
+ item->txn_queue = g_queue_new ();
+ return item;
}
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
-static void da_acc_max_key_ghfunc(gpointer key, Account *item, guint32 *max_key)
-{
- *max_key = MAX(*max_key, item->key);
-}
-
-static gboolean da_acc_name_grfunc(gpointer key, Account *item, gchar *name)
-{
- if( name && item->name )
- {
- if(!strcasecmp(name, item->name))
- return TRUE;
- }
- return FALSE;
-}
-static gboolean da_acc_imp_name_grfunc(gpointer key, Account *item, gchar *name)
-{
- if( name && item->imp_name )
- {
- if(!strcasecmp(name, item->imp_name))
- return TRUE;
- }
- return FALSE;
-}
/**
* da_acc_length:
}
+static void da_acc_max_key_ghfunc(gpointer key, Account *item, guint32 *max_key)
+{
+ *max_key = MAX(*max_key, item->key);
+}
+
+
+/**
+ * da_acc_get_max_key:
+ *
+ * Get the biggest key from the GHashTable
+ *
+ * Return value: the biggest key value
+ *
+ */
+guint32
+da_acc_get_max_key(void)
+{
+guint32 max_key = 0;
+
+ g_hash_table_foreach(GLOBALS->h_acc, (GHFunc)da_acc_max_key_ghfunc, &max_key);
+ return max_key;
+}
+
+
/**
* da_acc_remove:
*
- * remove an account from the GHashTable
+ * delete an account from the GHashTable
*
- * Return value: TRUE if the key was found and removed
+ * Return value: TRUE if the key was found and deleted
*
*/
gboolean
da_acc_append(Account *item)
{
Account *existitem;
-guint32 *new_key;
DB( g_print("da_acc_append\n") );
- /* ensure no duplicate */
- g_strstrip(item->name);
- if(item->name != NULL)
+ existitem = da_acc_get_by_name( item->name );
+ if( existitem == NULL )
{
- existitem = da_acc_get_by_name( item->name );
- if( existitem == NULL )
- {
- new_key = g_new0(guint32, 1);
- *new_key = da_acc_get_max_key() + 1;
- item->key = *new_key;
- item->pos = da_acc_length() + 1;
-
- DB( g_print(" -> insert id: %d\n", *new_key) );
-
- g_hash_table_insert(GLOBALS->h_acc, new_key, item);
- return TRUE;
- }
+ item->key = da_acc_get_max_key() + 1;
+ item->pos = da_acc_length() + 1;
+ da_acc_insert(item);
+ return TRUE;
}
DB( g_print(" -> %s already exist: %d\n", item->name, item->key) );
return FALSE;
}
-/**
- * da_acc_get_max_key:
- *
- * Get the biggest key from the GHashTable
- *
- * Return value: the biggest key value
- *
- */
-guint32
-da_acc_get_max_key(void)
-{
-guint32 max_key = 0;
- g_hash_table_foreach(GLOBALS->h_acc, (GHFunc)da_acc_max_key_ghfunc, &max_key);
- return max_key;
+static gboolean da_acc_name_grfunc(gpointer key, Account *item, gchar *name)
+{
+ if( name && item->name )
+ {
+ if(!strcasecmp(name, item->name))
+ return TRUE;
+ }
+ return FALSE;
}
-
-
-
/**
* da_acc_get_by_name:
*
*
*/
Account *
-da_acc_get_by_name(gchar *name)
+da_acc_get_by_name(gchar *rawname)
{
+Account *retval = NULL;
+gchar *stripname;
+
DB( g_print("da_acc_get_by_name\n") );
- return g_hash_table_find(GLOBALS->h_acc, (GHRFunc)da_acc_name_grfunc, name);
-}
+ if( rawname )
+ {
+ stripname = g_strdup(rawname);
+ g_strstrip(stripname);
+ if( strlen(stripname) > 0 )
+ retval = g_hash_table_find(GLOBALS->h_acc, (GHRFunc)da_acc_name_grfunc, stripname);
-Account *
-da_acc_get_by_imp_name(gchar *name)
-{
- DB( g_print("da_acc_get_by_imp_name\n") );
+ g_free(stripname);
+ }
- return g_hash_table_find(GLOBALS->h_acc, (GHRFunc)da_acc_imp_name_grfunc, name);
+ return retval;
}
gboolean
account_is_used(guint32 key)
{
+Account *acc;
GList *list;
+GList *lst_acc, *lnk_acc;
+GList *lnk_txn;
+gboolean retval;
- list = g_list_first(GLOBALS->ope_list);
- while (list != NULL)
- {
- Transaction *entry = list->data;
- if( key == entry->kacc || key == entry->kxferacc)
- return TRUE;
- list = g_list_next(list);
- }
+ retval = FALSE;
+ lst_acc = NULL;
- list = g_list_first(GLOBALS->arc_list);
- while (list != NULL)
+ acc = da_acc_get(key);
+ if( g_queue_get_length(acc->txn_queue) > 0 )
{
- Archive *entry = list->data;
- if( key == entry->kacc || key == entry->kxferacc)
- return TRUE;
- list = g_list_next(list);
+ retval = TRUE;
+ goto end;
}
- return FALSE;
-}
-
-void
-account_move(guint32 key1, guint32 key2)
-{
-GList *list;
-
- list = g_list_first(GLOBALS->ope_list);
- while (list != NULL)
+ lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+ lnk_acc = g_list_first(lst_acc);
+ while (lnk_acc != NULL)
{
- Transaction *entry = list->data;
- if(entry->kacc == key1)
- entry->kacc = key2;
- if(entry->kxferacc == key1)
- entry->kxferacc = key2;
- list = g_list_next(list);
+ Account *acc = lnk_acc->data;
+
+ if(acc->key != key)
+ {
+ lnk_txn = g_queue_peek_head_link(acc->txn_queue);
+ while (lnk_txn != NULL)
+ {
+ Transaction *entry = lnk_txn->data;
+
+ if( key == entry->kxferacc)
+ {
+ retval = TRUE;
+ goto end;
+ }
+
+ lnk_txn = g_list_next(lnk_txn);
+ }
+ }
+ lnk_acc = g_list_next(lnk_acc);
}
list = g_list_first(GLOBALS->arc_list);
while (list != NULL)
{
Archive *entry = list->data;
- if(entry->kacc == key1)
- entry->kacc = key2;
- if(entry->kxferacc == key1)
- entry->kxferacc = key2;
+
+ if( key == entry->kacc || key == entry->kxferacc)
+ {
+ retval = TRUE;
+ goto end;
+ }
+
list = g_list_next(list);
}
+
+end:
+ g_list_free(lst_acc);
+
+ return retval;
}
+
static gchar *
account_get_stripname(gchar *name)
{
Account *existitem;
gchar *stripname = account_get_stripname(newname);
- existitem = da_acc_get_by_name(stripname);
- if( existitem == NULL )
+ if( strlen(stripname) > 0 )
{
- g_free(item->name);
- item->name = g_strdup(stripname);
- return TRUE;
- }
-
- g_free(stripname);
+ existitem = da_acc_get_by_name(stripname);
+ if( existitem == NULL )
+ {
+ g_free(item->name);
+ item->name = g_strdup(stripname);
+ return TRUE;
+ }
+ g_free(stripname);
+ }
+
return FALSE;
}
-/* when we change the currency of an account, we must ensure
- * xfer transaction account will be set to same currency
+
+/*
+ * change the account currency
+ * change every txn to currency
+ * ensure dst xfer transaction account will be set to same currency
*/
- /*
-void account_set_currency(Account *item, guint32 kcur)
+void account_set_currency(Account *acc, guint32 kcur)
{
GList *list;
-Account *acc;
+Account *dstacc;
+gboolean *xfer_list;
+guint32 maxkey, i;
+
+ DB( g_print("\n[account] set currency\n") );
- if(item->kcur != kcur)
+ if(acc->kcur == kcur)
{
- item->kcur = kcur;
-
- list = g_list_first(GLOBALS->ope_list);
- while (list != NULL)
+ DB( g_print(" - already ok, return\n") );
+ return;
+ }
+
+ DB( g_print(" - set for '%s'\n", acc->name) );
+
+ maxkey = da_acc_get_max_key () + 1;
+ xfer_list = g_malloc0(sizeof(gboolean) * maxkey );
+ DB( g_print(" - alloc for %d account\n", da_acc_length() ) );
+
+ list = g_queue_peek_head_link(acc->txn_queue);
+ while (list != NULL)
+ {
+ Transaction *txn = list->data;
+
+ txn->kcur = kcur;
+ if( (txn->paymode == PAYMODE_INTXFER) && (txn->kxferacc > 0) && (txn->kxfer > 0) )
{
- Transaction *entry = list->data;
- if(entry->paymode == PAYMODE_INTXFER)
- {
- if(entry->kacc == item->key)
- {
- // change target account
- acc = da_acc_get (entry->kxferacc);
- acc->kcur = kcur;
- }
- if(entry->kxferacc == item->key)
- {
- // change source account
- acc = da_acc_get (entry->kacc);
- acc->kcur = kcur;
- }
- }
-
- list = g_list_next(list);
+ xfer_list[txn->kxferacc] = TRUE;
}
+ list = g_list_next(list);
}
+
+ acc->kcur = kcur;
+ DB( g_print(" - '%s'\n", acc->name) );
-}
-*/
+ for(i=1;i<maxkey;i++)
+ {
+ DB( g_print(" - %d '%d'\n", i, xfer_list[i]) );
+ if( xfer_list[i] == TRUE )
+ {
+ dstacc = da_acc_get(i);
+ account_set_currency(dstacc, kcur);
+ }
+ }
+ g_free(xfer_list);
+
+}
/**
if(trn->date <= GLOBALS->today)
acc->bal_today -= trn->amount;
- if(trn->flags & OF_VALID)
+ if(trn->status == TXN_STATUS_RECONCILED)
+ //if(trn->flags & OF_VALID)
acc->bal_bank -= trn->amount;
}
if(trn->date <= GLOBALS->today)
acc->bal_today += trn->amount;
- if(trn->flags & OF_VALID)
+ if(trn->status == TXN_STATUS_RECONCILED)
+ //if(trn->flags & OF_VALID)
acc->bal_bank += trn->amount;
}
*/
gboolean account_balances_sub(Transaction *trn)
{
- if(!(trn->flags & OF_REMIND))
+
+ if(!(trn->status == TXN_STATUS_REMIND))
+ //if(!(trn->flags & OF_REMIND))
{
Account *acc = da_acc_get(trn->kacc);
if(acc == NULL) return FALSE;
*/
gboolean account_balances_add(Transaction *trn)
{
- if(!(trn->flags & OF_REMIND))
+ if(!(trn->status == TXN_STATUS_REMIND))
+ //if(!(trn->flags & OF_REMIND))
{
Account *acc = da_acc_get(trn->kacc);
if(acc == NULL) return FALSE;
}
-
-
-
-
+//todo: optim called 2 times from dsp_mainwindow
void account_compute_balances(void)
{
-GList *lacc, *list;
-Account *acc;
-Transaction *trn;
+GList *lst_acc, *lnk_acc;
+GList *lnk_txn;
DB( g_print("\naccount_compute_balances start\n") );
- /* set initial amount */
- lacc = list = g_hash_table_get_values(GLOBALS->h_acc);
- while (list != NULL)
+ lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+ lnk_acc = g_list_first(lst_acc);
+ while (lnk_acc != NULL)
{
- acc = list->data;
+ Account *acc = lnk_acc->data;
+
+ /* set initial amount */
acc->bal_bank = acc->initial;
acc->bal_today = acc->initial;
acc->bal_future = acc->initial;
- list = g_list_next(list);
- }
- g_list_free(lacc);
-
-
- /* compute every transaction */
- list = g_list_first(GLOBALS->ope_list);
- while (list != NULL)
- {
- trn = list->data;
-
- if(!(trn->flags & OF_REMIND))
+
+ /* add every txn */
+ lnk_txn = g_queue_peek_head_link(acc->txn_queue);
+ while (lnk_txn != NULL)
{
- account_balances_add(trn);
+ Transaction *txn = lnk_txn->data;
+
+ if(!(txn->status == TXN_STATUS_REMIND))
+ {
+ account_balances_add_internal(acc, txn);
+ }
+ lnk_txn = g_list_next(lnk_txn);
}
- list = g_list_next(list);
+
+ lnk_acc = g_list_next(lnk_acc);
}
+ g_list_free(lst_acc);
DB( g_print("\naccount_compute_balances end\n") );
}
+void account_convert_euro(Account *acc)
+{
+GList *lnk_txn;
+
+ lnk_txn = g_queue_peek_head_link(acc->txn_queue);
+ while (lnk_txn != NULL)
+ {
+ Transaction *txn = lnk_txn->data;
+ gdouble oldamount = txn->amount;
+ txn->amount = hb_amount_to_euro(oldamount);
+ DB( g_print("%10.6f => %10.6f, %s\n", oldamount, txn->amount, txn->memo) );
+ //todo: sync child xfer
+ lnk_txn = g_list_next(lnk_txn);
+ }
+ acc->initial = hb_amount_to_euro(acc->initial);
+ acc->warning = hb_amount_to_euro(acc->warning);
+ acc->minimum = hb_amount_to_euro(acc->minimum);
+}