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