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