]> Dogcows Code - chaz/homebank/blob - src/hb-payee.c
import homebank-5.1.3
[chaz/homebank] / src / hb-payee.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2017 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-payee.h"
22
23
24 /****************************************************************************/
25 /* Debug macros */
26 /****************************************************************************/
27 #define MYDEBUG 0
28
29 #if MYDEBUG
30 #define DB(x) (x);
31 #else
32 #define DB(x);
33 #endif
34
35 /* our global datas */
36 extern struct HomeBank *GLOBALS;
37
38 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
39
40 void
41 da_pay_free(Payee *item)
42 {
43 DB( g_print("da_pay_free\n") );
44 if(item != NULL)
45 {
46 DB( g_print(" => %d, %s\n", item->key, item->name) );
47
48 g_free(item->name);
49 g_free(item);
50 }
51 }
52
53
54 Payee *
55 da_pay_malloc(void)
56 {
57 DB( g_print("da_pay_malloc\n") );
58 return g_malloc0(sizeof(Payee));
59 }
60
61
62 void
63 da_pay_destroy(void)
64 {
65 DB( g_print("da_pay_destroy\n") );
66 g_hash_table_destroy(GLOBALS->h_pay);
67 }
68
69
70 void
71 da_pay_new(void)
72 {
73 Payee *item;
74
75 DB( g_print("da_pay_new\n") );
76 GLOBALS->h_pay = g_hash_table_new_full(g_int_hash, g_int_equal, (GDestroyNotify)g_free, (GDestroyNotify)da_pay_free);
77
78 // insert our 'no payee'
79 item = da_pay_malloc();
80 item->name = g_strdup("");
81 da_pay_insert(item);
82 }
83
84
85 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
86 static void da_pay_max_key_ghfunc(gpointer key, Payee *item, guint32 *max_key)
87 {
88 *max_key = MAX(*max_key, item->key);
89 }
90
91 static gboolean da_pay_name_grfunc(gpointer key, Payee *item, gchar *name)
92 {
93 if( name && item->name )
94 {
95 if(!strcasecmp(name, item->name))
96 return TRUE;
97 }
98 return FALSE;
99 }
100
101 /**
102 * da_pay_length:
103 *
104 * Return value: the number of elements
105 */
106 guint
107 da_pay_length(void)
108 {
109 return g_hash_table_size(GLOBALS->h_pay);
110 }
111
112 /*
113 gboolean
114 da_pay_create_none(void)
115 {
116 Payee *pay;
117 guint32 *new_key;
118
119 DB( g_print("da_pay_insert none\n") );
120
121 pay = da_pay_malloc();
122 new_key = g_new0(guint32, 1);
123 *new_key = 0;
124 pay->key = 0;
125 pay->name = g_strdup("");
126
127 DB( g_print(" -> insert id: %d\n", *new_key) );
128
129 g_hash_table_insert(GLOBALS->h_pay, new_key, pay);
130
131
132 return TRUE;
133 }
134 */
135
136
137 /**
138 * da_pay_remove:
139 *
140 * delete an payee from the GHashTable
141 *
142 * Return value: TRUE if the key was found and deleted
143 *
144 */
145 gboolean
146 da_pay_remove(guint32 key)
147 {
148 DB( g_print("da_pay_remove %d\n", key) );
149
150 return g_hash_table_remove(GLOBALS->h_pay, &key);
151 }
152
153 /**
154 * da_pay_insert:
155 *
156 * insert an payee into the GHashTable
157 *
158 * Return value: TRUE if inserted
159 *
160 */
161 gboolean
162 da_pay_insert(Payee *item)
163 {
164 guint32 *new_key;
165
166 DB( g_print("da_pay_insert\n") );
167
168 new_key = g_new0(guint32, 1);
169 *new_key = item->key;
170 g_hash_table_insert(GLOBALS->h_pay, new_key, item);
171
172 return TRUE;
173 }
174
175
176 /**
177 * da_pay_append:
178 *
179 * append a new payee into the GHashTable
180 *
181 * Return value: TRUE if inserted
182 *
183 */
184 gboolean
185 da_pay_append(Payee *item)
186 {
187 Payee *existitem;
188 guint32 *new_key;
189
190 DB( g_print("da_pay_append\n") );
191
192 /* ensure no duplicate */
193 //g_strstrip(item->name);
194 if( item->name != NULL )
195 {
196 existitem = da_pay_get_by_name( item->name );
197 if( existitem == NULL )
198 {
199 new_key = g_new0(guint32, 1);
200 *new_key = da_pay_get_max_key() + 1;
201 item->key = *new_key;
202
203 DB( g_print(" -> append id: %d\n", *new_key) );
204
205 g_hash_table_insert(GLOBALS->h_pay, new_key, item);
206 return TRUE;
207 }
208 }
209
210 DB( g_print(" -> %s already exist: %d\n", item->name, item->key) );
211
212 return FALSE;
213 }
214
215 /**
216 * da_pay_get_max_key:
217 *
218 * Get the biggest key from the GHashTable
219 *
220 * Return value: the biggest key value
221 *
222 */
223 guint32
224 da_pay_get_max_key(void)
225 {
226 guint32 max_key = 0;
227
228 g_hash_table_foreach(GLOBALS->h_pay, (GHFunc)da_pay_max_key_ghfunc, &max_key);
229 return max_key;
230 }
231
232
233
234
235 /**
236 * da_pay_get_by_name:
237 *
238 * Get an payee structure by its name
239 *
240 * Return value: Payee * or NULL if not found
241 *
242 */
243 Payee *
244 da_pay_get_by_name(gchar *name)
245 {
246 DB( g_print("da_pay_get_by_name\n") );
247
248 return g_hash_table_find(GLOBALS->h_pay, (GHRFunc)da_pay_name_grfunc, name);
249 }
250
251
252
253 /**
254 * da_pay_get:
255 *
256 * Get an payee structure by key
257 *
258 * Return value: Payee * or NULL if not found
259 *
260 */
261 Payee *
262 da_pay_get(guint32 key)
263 {
264 //DB( g_print("da_pay_get\n") );
265
266 return g_hash_table_lookup(GLOBALS->h_pay, &key);
267 }
268
269
270 void da_pay_consistency(Payee *item)
271 {
272 g_strstrip(item->name);
273 }
274
275
276 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
277
278 #if MYDEBUG
279
280 static void
281 da_pay_debug_list_ghfunc(gpointer key, gpointer value, gpointer user_data)
282 {
283 guint32 *id = key;
284 Payee *item = value;
285
286 DB( g_print(" %d :: %s\n", *id, item->name) );
287
288 }
289
290 static void
291 da_pay_debug_list(void)
292 {
293
294 DB( g_print("\n** debug **\n") );
295
296 g_hash_table_foreach(GLOBALS->h_pay, da_pay_debug_list_ghfunc, NULL);
297
298 DB( g_print("\n** end debug **\n") );
299
300 }
301
302 #endif
303
304
305 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
306
307 void
308 payee_delete_unused(void)
309 {
310 GList *lpay, *list;
311
312 lpay = list = g_hash_table_get_values(GLOBALS->h_pay);
313 while (list != NULL)
314 {
315 Payee *entry = list->data;
316
317 if(entry->usage_count <= 0 && entry->key > 0)
318 da_pay_remove (entry->key);
319 list = g_list_next(list);
320 }
321 g_list_free(lpay);
322 }
323
324
325 void
326 payee_fill_usage(void)
327 {
328 GList *lpay;
329 GList *lst_acc, *lnk_acc;
330 GList *lnk_txn;
331 GList *lrul, *list;
332
333 lpay = list = g_hash_table_get_values(GLOBALS->h_pay);
334 while (list != NULL)
335 {
336 Payee *entry = list->data;
337 entry->usage_count = 0;
338 list = g_list_next(list);
339 }
340 g_list_free(lpay);
341
342
343 lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
344 lnk_acc = g_list_first(lst_acc);
345 while (lnk_acc != NULL)
346 {
347 Account *acc = lnk_acc->data;
348
349 lnk_txn = g_queue_peek_head_link(acc->txn_queue);
350 while (lnk_txn != NULL)
351 {
352 Transaction *txn = lnk_txn->data;
353 Payee *pay = da_pay_get (txn->kpay);
354
355 if(pay)
356 pay->usage_count++;
357
358 lnk_txn = g_list_next(lnk_txn);
359 }
360
361 lnk_acc = g_list_next(lnk_acc);
362 }
363 g_list_free(lst_acc);
364
365
366 list = g_list_first(GLOBALS->arc_list);
367 while (list != NULL)
368 {
369 Archive *entry = list->data;
370 Payee *pay = da_pay_get (entry->kpay);
371
372 if(pay)
373 pay->usage_count++;
374 list = g_list_next(list);
375 }
376
377 lrul = list = g_hash_table_get_values(GLOBALS->h_rul);
378 while (list != NULL)
379 {
380 Assign *entry = list->data;
381 Payee *pay = da_pay_get (entry->kpay);
382
383 if(pay)
384 pay->usage_count++;
385
386 list = g_list_next(list);
387 }
388 g_list_free(lrul);
389
390 }
391
392
393 void
394 payee_move(guint32 key1, guint32 key2)
395 {
396 GList *lst_acc, *lnk_acc;
397 GList *lnk_txn;
398 GList *lrul, *list;
399
400 lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
401 lnk_acc = g_list_first(lst_acc);
402 while (lnk_acc != NULL)
403 {
404 Account *acc = lnk_acc->data;
405
406 lnk_txn = g_queue_peek_head_link(acc->txn_queue);
407 while (lnk_txn != NULL)
408 {
409 Transaction *txn = lnk_txn->data;
410
411 if(txn->kpay == key1)
412 {
413 txn->kpay = key2;
414 txn->flags |= OF_CHANGED;
415 }
416 lnk_txn = g_list_next(lnk_txn);
417 }
418 lnk_acc = g_list_next(lnk_acc);
419 }
420 g_list_free(lst_acc);
421
422
423 list = g_list_first(GLOBALS->arc_list);
424 while (list != NULL)
425 {
426 Archive *entry = list->data;
427 if(entry->kpay == key1)
428 {
429 entry->kpay = key2;
430 }
431 list = g_list_next(list);
432 }
433
434 lrul = list = g_hash_table_get_values(GLOBALS->h_rul);
435 while (list != NULL)
436 {
437 Assign *entry = list->data;
438
439 if(entry->kpay == key1)
440 {
441 entry->kpay = key2;
442 }
443 list = g_list_next(list);
444 }
445 g_list_free(lrul);
446 }
447
448
449 gboolean
450 payee_rename(Payee *item, const gchar *newname)
451 {
452 Payee *existitem;
453 gchar *stripname;
454
455 stripname = g_strdup(newname);
456 g_strstrip(stripname);
457
458 existitem = da_pay_get_by_name(stripname);
459
460 if( existitem != NULL )
461 {
462 if( existitem->key == item->key )
463 return TRUE;
464 }
465 else
466 {
467 g_free(item->name);
468 item->name = g_strdup(stripname);
469 return TRUE;
470 }
471
472 g_free(stripname);
473
474 return FALSE;
475 }
476
477
478 /**
479 * payee_append_if_new:
480 *
481 * append a new payee into the GHashTable
482 *
483 * Return value: true/false + new payee
484 *
485 */
486 gboolean
487 payee_append_if_new(gchar *name, Payee **newpayee)
488 {
489 gboolean retval = FALSE;
490 gchar *stripname = g_strdup(name);
491 Payee *item;
492
493 g_strstrip(stripname);
494 item = da_pay_get_by_name(stripname);
495 if(item == NULL)
496 {
497 item = da_pay_malloc();
498 item->name = g_strdup(stripname);
499 da_pay_append(item);
500 retval = TRUE;
501 }
502 if( newpayee != NULL )
503 *newpayee = item;
504
505 g_free(stripname);
506
507 return retval;
508 }
509
510 static gint
511 payee_glist_name_compare_func(Payee *a, Payee *b)
512 {
513 return hb_string_utf8_compare(a->name, b->name);
514 }
515
516
517 static gint
518 payee_glist_key_compare_func(Payee *a, Payee *b)
519 {
520 return a->key - b->key;
521 }
522
523
524 GList *payee_glist_sorted(gint column)
525 {
526 GList *list = g_hash_table_get_values(GLOBALS->h_pay);
527
528 if(column == 0)
529 return g_list_sort(list, (GCompareFunc)payee_glist_key_compare_func);
530 else
531 return g_list_sort(list, (GCompareFunc)payee_glist_name_compare_func);
532 }
533
534
535
536 gboolean
537 payee_load_csv(gchar *filename, gchar **error)
538 {
539 gboolean retval;
540 GIOChannel *io;
541 gchar *tmpstr;
542 gint io_stat;
543 gchar **str_array;
544 const gchar *encoding;
545 gint nbcol;
546
547 encoding = homebank_file_getencoding(filename);
548
549 retval = TRUE;
550 *error = NULL;
551 io = g_io_channel_new_file(filename, "r", NULL);
552 if(io != NULL)
553 {
554 DB( g_print(" -> encoding should be %s\n", encoding) );
555 if( encoding != NULL )
556 {
557 g_io_channel_set_encoding(io, encoding, NULL);
558 }
559
560 for(;;)
561 {
562 io_stat = g_io_channel_read_line(io, &tmpstr, NULL, NULL, NULL);
563 if( io_stat == G_IO_STATUS_EOF)
564 break;
565 if( io_stat == G_IO_STATUS_NORMAL)
566 {
567 if( tmpstr != NULL)
568 {
569 DB( g_print("\n + strip\n") );
570 hb_string_strip_crlf(tmpstr);
571
572 DB( g_print(" + split '%s'\n", tmpstr) );
573 str_array = g_strsplit (tmpstr, ";", 2);
574 // payee;category : later paymode?
575
576 nbcol = g_strv_length (str_array);
577 if( nbcol > 2 )
578 {
579 *error = _("invalid CSV format");
580 retval = FALSE;
581 DB( g_print(" + error %s\n", *error) );
582 }
583 else
584 {
585 gboolean added;
586 Payee *pay = NULL;
587
588 if( nbcol >= 1 )
589 {
590 DB( g_print(" add pay:'%s' ?\n", str_array[0]) );
591 added = payee_append_if_new(str_array[0], &pay);
592 if( added )
593 {
594 DB( g_print(" added: %p\n", pay) );
595 GLOBALS->changes_count++;
596 }
597 }
598
599 if( nbcol == 2 )
600 {
601 Category *cat;
602
603 DB( g_print(" add cat:'%s'\n", str_array[1]) );
604 cat = da_cat_append_ifnew_by_fullname(str_array[1], FALSE);
605
606 DB( g_print(" cat: %p %p\n", cat, pay) );
607 if( cat != NULL )
608 {
609 if( pay != NULL)
610 {
611 DB( g_print(" set default cat to %d\n", cat->key) );
612 pay->kcat = cat->key;
613 }
614 GLOBALS->changes_count++;
615 }
616 }
617 }
618 g_strfreev (str_array);
619 }
620 g_free(tmpstr);
621 }
622
623 }
624 g_io_channel_unref (io);
625 }
626
627 return retval;
628 }
629
630
631 void
632 payee_save_csv(gchar *filename)
633 {
634 GIOChannel *io;
635 GList *lpay, *list;
636 gchar *outstr;
637
638 io = g_io_channel_new_file(filename, "w", NULL);
639 if(io != NULL)
640 {
641 lpay = list = payee_glist_sorted(1);
642
643 while (list != NULL)
644 {
645 Payee *item = list->data;
646 gchar *fullcatname;
647
648 if(item->key != 0)
649 {
650 fullcatname = NULL;
651 if( item->kcat > 0 )
652 {
653 Category *cat = da_cat_get(item->kcat);
654
655 if( cat != NULL )
656 {
657 fullcatname = da_cat_get_fullname (cat);
658 }
659 }
660
661 if( fullcatname != NULL )
662 outstr = g_strdup_printf("%s;%s\n", item->name, fullcatname);
663 else
664 outstr = g_strdup_printf("%s;\n", item->name);
665
666 DB( g_print(" + export %s\n", outstr) );
667
668 g_io_channel_write_chars(io, outstr, -1, NULL, NULL);
669
670 g_free(outstr);
671 g_free(fullcatname);
672
673 }
674 list = g_list_next(list);
675 }
676 g_list_free(lpay);
677
678 g_io_channel_unref (io);
679 }
680
681 }
682
683
This page took 0.059414 seconds and 4 git commands to generate.