add gitignore
[chaz/homebank] / src / hb-account.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2014 Maxime DOYEN
3 *
4 * This file is part of HomeBank.
5 *
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.
10 *
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.
15 *
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/>.
18 */
19
20 #include "homebank.h"
21 #include "hb-account.h"
22
23 /****************************************************************************/
24 /* Debug macros */
25 /****************************************************************************/
26 #define MYDEBUG 0
27
28 #if MYDEBUG
29 #define DB(x) (x);
30 #else
31 #define DB(x);
32 #endif
33
34 /* our global datas */
35 extern struct HomeBank *GLOBALS;
36
37
38
39
40
41 Account *
42 da_acc_clone(Account *src_item)
43 {
44 Account *new_item = g_memdup(src_item, sizeof(Account));
45
46 DB( g_print("da_acc_clone\n") );
47 if(new_item)
48 {
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);
53 }
54 return new_item;
55 }
56
57
58 void
59 da_acc_free(Account *item)
60 {
61 DB( g_print("da_acc_free\n") );
62 if(item != NULL)
63 {
64 DB( g_print(" => %d, %s\n", item->key, item->name) );
65
66 g_free(item->imp_name);
67 g_free(item->name);
68 g_free(item->number);
69 g_free(item->bankname);
70 g_free(item);
71 }
72 }
73
74
75 Account *
76 da_acc_malloc(void)
77 {
78 DB( g_print("da_acc_malloc\n") );
79 return g_malloc0(sizeof(Account));
80 }
81
82
83 void
84 da_acc_destroy(void)
85 {
86 DB( g_print("da_acc_destroy\n") );
87 g_hash_table_destroy(GLOBALS->h_acc);
88 }
89
90
91 void
92 da_acc_new(void)
93 {
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);
96 }
97
98
99 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
100 static void da_acc_max_key_ghfunc(gpointer key, Account *item, guint32 *max_key)
101 {
102 *max_key = MAX(*max_key, item->key);
103 }
104
105 static gboolean da_acc_name_grfunc(gpointer key, Account *item, gchar *name)
106 {
107 if( name && item->name )
108 {
109 if(!strcasecmp(name, item->name))
110 return TRUE;
111 }
112 return FALSE;
113 }
114
115 static gboolean da_acc_imp_name_grfunc(gpointer key, Account *item, gchar *name)
116 {
117 if( name && item->imp_name )
118 {
119 if(!strcasecmp(name, item->imp_name))
120 return TRUE;
121 }
122 return FALSE;
123 }
124
125 /**
126 * da_acc_length:
127 *
128 * Return value: the number of elements
129 */
130 guint
131 da_acc_length(void)
132 {
133 return g_hash_table_size(GLOBALS->h_acc);
134 }
135
136
137 /**
138 * da_acc_remove:
139 *
140 * remove an account from the GHashTable
141 *
142 * Return value: TRUE if the key was found and removed
143 *
144 */
145 gboolean
146 da_acc_remove(guint32 key)
147 {
148 DB( g_print("da_acc_remove %d\n", key) );
149
150 return g_hash_table_remove(GLOBALS->h_acc, &key);
151 }
152
153 /**
154 * da_acc_insert:
155 *
156 * insert an account into the GHashTable
157 *
158 * Return value: TRUE if inserted
159 *
160 */
161 gboolean
162 da_acc_insert(Account *item)
163 {
164 guint32 *new_key;
165
166 DB( g_print("da_acc_insert\n") );
167
168 new_key = g_new0(guint32, 1);
169 *new_key = item->key;
170 g_hash_table_insert(GLOBALS->h_acc, new_key, item);
171
172 return TRUE;
173 }
174
175
176 /**
177 * da_acc_append:
178 *
179 * insert an account into the GHashTable
180 *
181 * Return value: TRUE if inserted
182 *
183 */
184 gboolean
185 da_acc_append(Account *item)
186 {
187 Account *existitem;
188 guint32 *new_key;
189
190 DB( g_print("da_acc_append\n") );
191
192 /* ensure no duplicate */
193 g_strstrip(item->name);
194 if(item->name != NULL)
195 {
196 existitem = da_acc_get_by_name( item->name );
197 if( existitem == NULL )
198 {
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;
203
204 DB( g_print(" -> insert id: %d\n", *new_key) );
205
206 g_hash_table_insert(GLOBALS->h_acc, new_key, item);
207 return TRUE;
208 }
209 }
210
211 DB( g_print(" -> %s already exist: %d\n", item->name, item->key) );
212
213 return FALSE;
214 }
215
216 /**
217 * da_acc_get_max_key:
218 *
219 * Get the biggest key from the GHashTable
220 *
221 * Return value: the biggest key value
222 *
223 */
224 guint32
225 da_acc_get_max_key(void)
226 {
227 guint32 max_key = 0;
228
229 g_hash_table_foreach(GLOBALS->h_acc, (GHFunc)da_acc_max_key_ghfunc, &max_key);
230 return max_key;
231 }
232
233
234
235
236 /**
237 * da_acc_get_by_name:
238 *
239 * Get an account structure by its name
240 *
241 * Return value: Account * or NULL if not found
242 *
243 */
244 Account *
245 da_acc_get_by_name(gchar *name)
246 {
247 DB( g_print("da_acc_get_by_name\n") );
248
249 return g_hash_table_find(GLOBALS->h_acc, (GHRFunc)da_acc_name_grfunc, name);
250 }
251
252 Account *
253 da_acc_get_by_imp_name(gchar *name)
254 {
255 DB( g_print("da_acc_get_by_imp_name\n") );
256
257 return g_hash_table_find(GLOBALS->h_acc, (GHRFunc)da_acc_imp_name_grfunc, name);
258 }
259
260
261 /**
262 * da_acc_get:
263 *
264 * Get an account structure by key
265 *
266 * Return value: Account * or NULL if not found
267 *
268 */
269 Account *
270 da_acc_get(guint32 key)
271 {
272 //DB( g_print("da_acc_get\n") );
273
274 return g_hash_table_lookup(GLOBALS->h_acc, &key);
275 }
276
277
278 void da_acc_consistency(Account *item)
279 {
280 g_strstrip(item->name);
281 }
282
283
284 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
285 #if MYDEBUG
286
287 static void
288 da_acc_debug_list_ghfunc(gpointer key, gpointer value, gpointer user_data)
289 {
290 guint32 *id = key;
291 Account *item = value;
292
293 DB( g_print(" %d :: %s\n", *id, item->name) );
294
295 }
296
297 static void
298 da_acc_debug_list(void)
299 {
300
301 DB( g_print("\n** debug **\n") );
302
303 g_hash_table_foreach(GLOBALS->h_acc, da_acc_debug_list_ghfunc, NULL);
304
305 DB( g_print("\n** end debug **\n") );
306
307 }
308
309 #endif
310
311
312 static gint
313 account_glist_name_compare_func(Account *a, Account *b)
314 {
315 return hb_string_utf8_compare(a->name, b->name);
316 }
317
318
319 static gint
320 account_glist_key_compare_func(Account *a, Account *b)
321 {
322 return a->key - b->key;
323 }
324
325
326 GList *account_glist_sorted(gint column)
327 {
328 GList *list = g_hash_table_get_values(GLOBALS->h_acc);
329
330 if(column == 0)
331 return g_list_sort(list, (GCompareFunc)account_glist_key_compare_func);
332 else
333 return g_list_sort(list, (GCompareFunc)account_glist_name_compare_func);
334 }
335
336
337
338 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
339
340
341
342
343 /**
344 * account_is_used:
345 *
346 * controls if an account is used by any archive or transaction
347 *
348 * Return value: TRUE if used, FALSE, otherwise
349 */
350 gboolean
351 account_is_used(guint32 key)
352 {
353 GList *list;
354
355 list = g_list_first(GLOBALS->ope_list);
356 while (list != NULL)
357 {
358 Transaction *entry = list->data;
359 if( key == entry->kacc || key == entry->kxferacc)
360 return TRUE;
361 list = g_list_next(list);
362 }
363
364 list = g_list_first(GLOBALS->arc_list);
365 while (list != NULL)
366 {
367 Archive *entry = list->data;
368 if( key == entry->kacc || key == entry->kxferacc)
369 return TRUE;
370 list = g_list_next(list);
371 }
372
373 return FALSE;
374 }
375
376 void
377 account_move(guint32 key1, guint32 key2)
378 {
379 GList *list;
380
381 list = g_list_first(GLOBALS->ope_list);
382 while (list != NULL)
383 {
384 Transaction *entry = list->data;
385 if(entry->kacc == key1)
386 entry->kacc = key2;
387 if(entry->kxferacc == key1)
388 entry->kxferacc = key2;
389 list = g_list_next(list);
390 }
391
392 list = g_list_first(GLOBALS->arc_list);
393 while (list != NULL)
394 {
395 Archive *entry = list->data;
396 if(entry->kacc == key1)
397 entry->kacc = key2;
398 if(entry->kxferacc == key1)
399 entry->kxferacc = key2;
400 list = g_list_next(list);
401 }
402 }
403
404 static gchar *
405 account_get_stripname(gchar *name)
406 {
407 gchar *stripname = g_strdup(name);
408 g_strstrip(stripname);
409
410 return stripname;
411 }
412
413
414 gboolean
415 account_exists(gchar *name)
416 {
417 Account *existitem;
418 gchar *stripname = account_get_stripname(name);
419
420 existitem = da_acc_get_by_name(stripname);
421 g_free(stripname);
422
423 return existitem == NULL ? FALSE : TRUE;
424 }
425
426
427 gboolean
428 account_rename(Account *item, gchar *newname)
429 {
430 Account *existitem;
431 gchar *stripname = account_get_stripname(newname);
432
433 existitem = da_acc_get_by_name(stripname);
434 if( existitem == NULL )
435 {
436 g_free(item->name);
437 item->name = g_strdup(stripname);
438 return TRUE;
439 }
440
441 g_free(stripname);
442
443 return FALSE;
444 }
445
446 /* when we change the currency of an account, we must ensure
447 * xfer transaction account will be set to same currency
448 */
449 /*
450 void account_set_currency(Account *item, guint32 kcur)
451 {
452 GList *list;
453 Account *acc;
454
455 if(item->kcur != kcur)
456 {
457 item->kcur = kcur;
458
459 list = g_list_first(GLOBALS->ope_list);
460 while (list != NULL)
461 {
462 Transaction *entry = list->data;
463 if(entry->paymode == PAYMODE_INTXFER)
464 {
465 if(entry->kacc == item->key)
466 {
467 // change target account
468 acc = da_acc_get (entry->kxferacc);
469 acc->kcur = kcur;
470 }
471 if(entry->kxferacc == item->key)
472 {
473 // change source account
474 acc = da_acc_get (entry->kacc);
475 acc->kcur = kcur;
476 }
477 }
478
479 list = g_list_next(list);
480 }
481 }
482
483 }
484 */
485
486
487
488 /**
489 * private function to sub transaction amount from account balances
490 */
491 static void account_balances_sub_internal(Account *acc, Transaction *trn)
492 {
493 acc->bal_future -= trn->amount;
494
495 if(trn->date <= GLOBALS->today)
496 acc->bal_today -= trn->amount;
497
498 if(trn->flags & OF_VALID)
499 acc->bal_bank -= trn->amount;
500 }
501
502 /**
503 * private function to add transaction amount from account balances
504 */
505 static void account_balances_add_internal(Account *acc, Transaction *trn)
506 {
507 acc->bal_future += trn->amount;
508
509 if(trn->date <= GLOBALS->today)
510 acc->bal_today += trn->amount;
511
512 if(trn->flags & OF_VALID)
513 acc->bal_bank += trn->amount;
514 }
515
516
517 /**
518 * public function to sub transaction amount from account balances
519 */
520 gboolean account_balances_sub(Transaction *trn)
521 {
522 if(!(trn->flags & OF_REMIND))
523 {
524 Account *acc = da_acc_get(trn->kacc);
525 if(acc == NULL) return FALSE;
526 account_balances_sub_internal(acc, trn);
527 return TRUE;
528 }
529 return FALSE;
530 }
531
532
533 /**
534 * public function to add transaction amount from account balances
535 */
536 gboolean account_balances_add(Transaction *trn)
537 {
538 if(!(trn->flags & OF_REMIND))
539 {
540 Account *acc = da_acc_get(trn->kacc);
541 if(acc == NULL) return FALSE;
542 account_balances_add_internal(acc, trn);
543 return TRUE;
544 }
545 return FALSE;
546 }
547
548
549
550
551
552
553 void account_compute_balances(void)
554 {
555 GList *lacc, *list;
556 Account *acc;
557 Transaction *trn;
558
559 DB( g_print("\naccount_compute_balances start\n") );
560
561 /* set initial amount */
562 lacc = list = g_hash_table_get_values(GLOBALS->h_acc);
563 while (list != NULL)
564 {
565 acc = list->data;
566 acc->bal_bank = acc->initial;
567 acc->bal_today = acc->initial;
568 acc->bal_future = acc->initial;
569 list = g_list_next(list);
570 }
571 g_list_free(lacc);
572
573
574 /* compute every transaction */
575 list = g_list_first(GLOBALS->ope_list);
576 while (list != NULL)
577 {
578 trn = list->data;
579
580 if(!(trn->flags & OF_REMIND))
581 {
582 account_balances_add(trn);
583 }
584 list = g_list_next(list);
585 }
586
587 DB( g_print("\naccount_compute_balances end\n") );
588
589 }
590
591
592
593
594
This page took 0.07144 seconds and 4 git commands to generate.