1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2014 Maxime DOYEN
4 * This file is part of HomeBank.
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "hb-account.h"
23 /****************************************************************************/
25 /****************************************************************************/
34 /* our global datas */
35 extern struct HomeBank
*GLOBALS
;
42 da_acc_clone(Account
*src_item
)
44 Account
*new_item
= g_memdup(src_item
, sizeof(Account
));
46 DB( g_print("da_acc_clone\n") );
49 //duplicate the string
50 new_item
->name
= g_strdup(src_item
->name
);
51 new_item
->number
= g_strdup(src_item
->number
);
52 new_item
->bankname
= g_strdup(src_item
->bankname
);
59 da_acc_free(Account
*item
)
61 DB( g_print("da_acc_free\n") );
64 DB( g_print(" => %d, %s\n", item
->key
, item
->name
) );
66 g_free(item
->imp_name
);
69 g_free(item
->bankname
);
78 DB( g_print("da_acc_malloc\n") );
79 return g_malloc0(sizeof(Account
));
86 DB( g_print("da_acc_destroy\n") );
87 g_hash_table_destroy(GLOBALS
->h_acc
);
94 DB( g_print("da_acc_new\n") );
95 GLOBALS
->h_acc
= g_hash_table_new_full(g_int_hash
, g_int_equal
, (GDestroyNotify
)g_free
, (GDestroyNotify
)da_acc_free
);
99 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
100 static void da_acc_max_key_ghfunc(gpointer key
, Account
*item
, guint32
*max_key
)
102 *max_key
= MAX(*max_key
, item
->key
);
105 static gboolean
da_acc_name_grfunc(gpointer key
, Account
*item
, gchar
*name
)
107 if( name
&& item
->name
)
109 if(!strcasecmp(name
, item
->name
))
115 static gboolean
da_acc_imp_name_grfunc(gpointer key
, Account
*item
, gchar
*name
)
117 if( name
&& item
->imp_name
)
119 if(!strcasecmp(name
, item
->imp_name
))
128 * Return value: the number of elements
133 return g_hash_table_size(GLOBALS
->h_acc
);
140 * remove an account from the GHashTable
142 * Return value: TRUE if the key was found and removed
146 da_acc_remove(guint32 key
)
148 DB( g_print("da_acc_remove %d\n", key
) );
150 return g_hash_table_remove(GLOBALS
->h_acc
, &key
);
156 * insert an account into the GHashTable
158 * Return value: TRUE if inserted
162 da_acc_insert(Account
*item
)
166 DB( g_print("da_acc_insert\n") );
168 new_key
= g_new0(guint32
, 1);
169 *new_key
= item
->key
;
170 g_hash_table_insert(GLOBALS
->h_acc
, new_key
, item
);
179 * insert an account into the GHashTable
181 * Return value: TRUE if inserted
185 da_acc_append(Account
*item
)
190 DB( g_print("da_acc_append\n") );
192 /* ensure no duplicate */
193 g_strstrip(item
->name
);
194 if(item
->name
!= NULL
)
196 existitem
= da_acc_get_by_name( item
->name
);
197 if( existitem
== NULL
)
199 new_key
= g_new0(guint32
, 1);
200 *new_key
= da_acc_get_max_key() + 1;
201 item
->key
= *new_key
;
202 item
->pos
= da_acc_length() + 1;
204 DB( g_print(" -> insert id: %d\n", *new_key
) );
206 g_hash_table_insert(GLOBALS
->h_acc
, new_key
, item
);
211 DB( g_print(" -> %s already exist: %d\n", item
->name
, item
->key
) );
217 * da_acc_get_max_key:
219 * Get the biggest key from the GHashTable
221 * Return value: the biggest key value
225 da_acc_get_max_key(void)
229 g_hash_table_foreach(GLOBALS
->h_acc
, (GHFunc
)da_acc_max_key_ghfunc
, &max_key
);
237 * da_acc_get_by_name:
239 * Get an account structure by its name
241 * Return value: Account * or NULL if not found
245 da_acc_get_by_name(gchar
*name
)
247 DB( g_print("da_acc_get_by_name\n") );
249 return g_hash_table_find(GLOBALS
->h_acc
, (GHRFunc
)da_acc_name_grfunc
, name
);
253 da_acc_get_by_imp_name(gchar
*name
)
255 DB( g_print("da_acc_get_by_imp_name\n") );
257 return g_hash_table_find(GLOBALS
->h_acc
, (GHRFunc
)da_acc_imp_name_grfunc
, name
);
264 * Get an account structure by key
266 * Return value: Account * or NULL if not found
270 da_acc_get(guint32 key
)
272 //DB( g_print("da_acc_get\n") );
274 return g_hash_table_lookup(GLOBALS
->h_acc
, &key
);
278 void da_acc_consistency(Account
*item
)
280 g_strstrip(item
->name
);
284 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
288 da_acc_debug_list_ghfunc(gpointer key
, gpointer value
, gpointer user_data
)
291 Account
*item
= value
;
293 DB( g_print(" %d :: %s\n", *id
, item
->name
) );
298 da_acc_debug_list(void)
301 DB( g_print("\n** debug **\n") );
303 g_hash_table_foreach(GLOBALS
->h_acc
, da_acc_debug_list_ghfunc
, NULL
);
305 DB( g_print("\n** end debug **\n") );
313 account_glist_name_compare_func(Account
*a
, Account
*b
)
315 return hb_string_utf8_compare(a
->name
, b
->name
);
320 account_glist_key_compare_func(Account
*a
, Account
*b
)
322 return a
->key
- b
->key
;
326 GList
*account_glist_sorted(gint column
)
328 GList
*list
= g_hash_table_get_values(GLOBALS
->h_acc
);
331 return g_list_sort(list
, (GCompareFunc
)account_glist_key_compare_func
);
333 return g_list_sort(list
, (GCompareFunc
)account_glist_name_compare_func
);
338 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
346 * controls if an account is used by any archive or transaction
348 * Return value: TRUE if used, FALSE, otherwise
351 account_is_used(guint32 key
)
355 list
= g_list_first(GLOBALS
->ope_list
);
358 Transaction
*entry
= list
->data
;
359 if( key
== entry
->kacc
|| key
== entry
->kxferacc
)
361 list
= g_list_next(list
);
364 list
= g_list_first(GLOBALS
->arc_list
);
367 Archive
*entry
= list
->data
;
368 if( key
== entry
->kacc
|| key
== entry
->kxferacc
)
370 list
= g_list_next(list
);
377 account_move(guint32 key1
, guint32 key2
)
381 list
= g_list_first(GLOBALS
->ope_list
);
384 Transaction
*entry
= list
->data
;
385 if(entry
->kacc
== key1
)
387 if(entry
->kxferacc
== key1
)
388 entry
->kxferacc
= key2
;
389 list
= g_list_next(list
);
392 list
= g_list_first(GLOBALS
->arc_list
);
395 Archive
*entry
= list
->data
;
396 if(entry
->kacc
== key1
)
398 if(entry
->kxferacc
== key1
)
399 entry
->kxferacc
= key2
;
400 list
= g_list_next(list
);
405 account_get_stripname(gchar
*name
)
407 gchar
*stripname
= g_strdup(name
);
408 g_strstrip(stripname
);
415 account_exists(gchar
*name
)
418 gchar
*stripname
= account_get_stripname(name
);
420 existitem
= da_acc_get_by_name(stripname
);
423 return existitem
== NULL
? FALSE
: TRUE
;
428 account_rename(Account
*item
, gchar
*newname
)
431 gchar
*stripname
= account_get_stripname(newname
);
433 existitem
= da_acc_get_by_name(stripname
);
434 if( existitem
== NULL
)
437 item
->name
= g_strdup(stripname
);
446 /* when we change the currency of an account, we must ensure
447 * xfer transaction account will be set to same currency
450 void account_set_currency(Account *item, guint32 kcur)
455 if(item->kcur != kcur)
459 list = g_list_first(GLOBALS->ope_list);
462 Transaction *entry = list->data;
463 if(entry->paymode == PAYMODE_INTXFER)
465 if(entry->kacc == item->key)
467 // change target account
468 acc = da_acc_get (entry->kxferacc);
471 if(entry->kxferacc == item->key)
473 // change source account
474 acc = da_acc_get (entry->kacc);
479 list = g_list_next(list);
489 * private function to sub transaction amount from account balances
491 static void account_balances_sub_internal(Account
*acc
, Transaction
*trn
)
493 acc
->bal_future
-= trn
->amount
;
495 if(trn
->date
<= GLOBALS
->today
)
496 acc
->bal_today
-= trn
->amount
;
498 if(trn
->flags
& OF_VALID
)
499 acc
->bal_bank
-= trn
->amount
;
503 * private function to add transaction amount from account balances
505 static void account_balances_add_internal(Account
*acc
, Transaction
*trn
)
507 acc
->bal_future
+= trn
->amount
;
509 if(trn
->date
<= GLOBALS
->today
)
510 acc
->bal_today
+= trn
->amount
;
512 if(trn
->flags
& OF_VALID
)
513 acc
->bal_bank
+= trn
->amount
;
518 * public function to sub transaction amount from account balances
520 gboolean
account_balances_sub(Transaction
*trn
)
522 if(!(trn
->flags
& OF_REMIND
))
524 Account
*acc
= da_acc_get(trn
->kacc
);
525 if(acc
== NULL
) return FALSE
;
526 account_balances_sub_internal(acc
, trn
);
534 * public function to add transaction amount from account balances
536 gboolean
account_balances_add(Transaction
*trn
)
538 if(!(trn
->flags
& OF_REMIND
))
540 Account
*acc
= da_acc_get(trn
->kacc
);
541 if(acc
== NULL
) return FALSE
;
542 account_balances_add_internal(acc
, trn
);
553 void account_compute_balances(void)
559 DB( g_print("\naccount_compute_balances start\n") );
561 /* set initial amount */
562 lacc
= list
= g_hash_table_get_values(GLOBALS
->h_acc
);
566 acc
->bal_bank
= acc
->initial
;
567 acc
->bal_today
= acc
->initial
;
568 acc
->bal_future
= acc
->initial
;
569 list
= g_list_next(list
);
574 /* compute every transaction */
575 list
= g_list_first(GLOBALS
->ope_list
);
580 if(!(trn
->flags
& OF_REMIND
))
582 account_balances_add(trn
);
584 list
= g_list_next(list
);
587 DB( g_print("\naccount_compute_balances end\n") );