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