GnuCash c935c2f+
Loading...
Searching...
No Matches
gncTaxTable.c
1/********************************************************************\
2 * gncTaxTable.c -- the Gnucash Tax Table interface *
3 * *
4 * This program is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU General Public License as *
6 * published by the Free Software Foundation; either version 2 of *
7 * the License, or (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License*
15 * along with this program; if not, contact: *
16 * *
17 * Free Software Foundation Voice: +1-617-542-5942 *
18 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
19 * Boston, MA 02110-1301, USA gnu@gnu.org *
20 * *
21\********************************************************************/
22
23/*
24 * Copyright (C) 2002 Derek Atkins
25 * Copyright (C) 2003 Linas Vepstas <linas@linas.org>
26 * Author: Derek Atkins <warlord@MIT.EDU>
27 */
28
29#include <config.h>
30
31#include <glib.h>
32#include <qofinstance-p.h>
33
34#include "gnc-features.h"
35#include "gncTaxTableP.h"
36
38{
39 QofInstance inst;
40 const char * name;
41 GncTaxTableEntryList* entries;
42 time64 modtime; /* internal date of last modtime */
43
44 /* See libgnucash/engine/TaxTableBillTermImmutability.txt for an explanation of the following */
45 /* Code that handles this is *identical* to that in gncBillTerm */
46 gint64 refcount;
47 GncTaxTable * parent; /* if non-null, we are an immutable child */
48 GncTaxTable * child; /* if non-null, we have not changed */
49 gboolean invisible;
50 GList * children; /* list of children for disconnection */
51};
52
54{
55 QofInstanceClass parent_class;
56};
57
59{
61 Account * account;
62 GncAmountType type;
63 gnc_numeric amount;
64};
65
66struct _book_info
67{
68 GList * tables; /* visible tables */
69};
70
71static QofLogModule log_module = GNC_MOD_BUSINESS;
72
73/* =============================================================== */
74/* You must edit the functions in this block in tandem. KEEP THEM IN
75 SYNC! */
76
77#define GNC_RETURN_ENUM_AS_STRING(x,s) case (x): return (s);
78const char *
79gncAmountTypeToString (GncAmountType type)
80{
81 switch (type)
82 {
83 GNC_RETURN_ENUM_AS_STRING(GNC_AMT_TYPE_VALUE, "VALUE");
84 GNC_RETURN_ENUM_AS_STRING(GNC_AMT_TYPE_PERCENT, "PERCENT");
85 default:
86 g_warning ("asked to translate unknown amount type %d.\n", type);
87 break;
88 }
89 return(NULL);
90}
91
92const char *
93gncTaxIncludedTypeToString (GncTaxIncluded type)
94{
95 switch (type)
96 {
97 GNC_RETURN_ENUM_AS_STRING(GNC_TAXINCLUDED_YES, "YES");
98 GNC_RETURN_ENUM_AS_STRING(GNC_TAXINCLUDED_NO, "NO");
99 GNC_RETURN_ENUM_AS_STRING(GNC_TAXINCLUDED_USEGLOBAL, "USEGLOBAL");
100 default:
101 g_warning ("asked to translate unknown taxincluded type %d.\n", type);
102 break;
103 }
104 return(NULL);
105}
106#undef GNC_RETURN_ENUM_AS_STRING
107#define GNC_RETURN_ON_MATCH(s,x) \
108 if(g_strcmp0((s), (str)) == 0) { *type = x; return(TRUE); }
109gboolean
110gncAmountStringToType (const char *str, GncAmountType *type)
111{
112 GNC_RETURN_ON_MATCH ("VALUE", GNC_AMT_TYPE_VALUE);
113 GNC_RETURN_ON_MATCH ("PERCENT", GNC_AMT_TYPE_PERCENT);
114 g_warning ("asked to translate unknown amount type string %s.\n",
115 str ? str : "(null)");
116
117 return(FALSE);
118}
119
120gboolean
121gncTaxIncludedStringToType (const char *str, GncTaxIncluded *type)
122{
123 GNC_RETURN_ON_MATCH ("YES", GNC_TAXINCLUDED_YES);
124 GNC_RETURN_ON_MATCH ("NO", GNC_TAXINCLUDED_NO);
125 GNC_RETURN_ON_MATCH ("USEGLOBAL", GNC_TAXINCLUDED_USEGLOBAL);
126 g_warning ("asked to translate unknown taxincluded type string %s.\n",
127 str ? str : "(null)");
128
129 return(FALSE);
130}
131#undef GNC_RETURN_ON_MATCH
132
133/* =============================================================== */
134/* Misc inline functions */
135
136#define _GNC_MOD_NAME GNC_ID_TAXTABLE
137
138#define SET_STR(obj, member, str) { \
139 if (!g_strcmp0 (member, str)) return; \
140 gncTaxTableBeginEdit (obj); \
141 CACHE_REPLACE (member, str); \
142 }
143
144static inline void
145mark_table (GncTaxTable *table)
146{
147 qof_instance_set_dirty(&table->inst);
148 qof_event_gen (&table->inst, QOF_EVENT_MODIFY, NULL);
149}
150
151static inline void
152maybe_resort_list (GncTaxTable *table)
153{
154 struct _book_info *bi;
155
156 if (table->parent || table->invisible) return;
157 bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
158 bi->tables = g_list_sort (bi->tables, (GCompareFunc)gncTaxTableCompare);
159}
160
161static inline void
162mod_table (GncTaxTable *table)
163{
164 table->modtime = gnc_time (NULL);
165}
166
167static inline void addObj (GncTaxTable *table)
168{
169 struct _book_info *bi;
170 bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
171 bi->tables = g_list_insert_sorted (bi->tables, table,
172 (GCompareFunc)gncTaxTableCompare);
173}
174
175static inline void remObj (GncTaxTable *table)
176{
177 struct _book_info *bi;
178 bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
179 bi->tables = g_list_remove (bi->tables, table);
180}
181
182static inline void
183gncTaxTableAddChild (GncTaxTable *table, GncTaxTable *child)
184{
185 g_return_if_fail(table);
186 g_return_if_fail(child);
187 g_return_if_fail(qof_instance_get_destroying(table) == FALSE);
188
189 table->children = g_list_prepend(table->children, child);
190}
191
192static inline void
193gncTaxTableRemoveChild (GncTaxTable *table, const GncTaxTable *child)
194{
195 g_return_if_fail(table);
196 g_return_if_fail(child);
197
199
200 table->children = g_list_remove(table->children, child);
201}
202
203/* =============================================================== */
204
205enum
206{
207 PROP_0,
208 PROP_NAME, /* Table */
209 PROP_INVISIBLE, /* Table */
210 PROP_REFCOUNT, /* Table */
211// PROP_PARENT, /* Table */
212};
213
214/* GObject Initialization */
215G_DEFINE_TYPE(GncTaxTable, gnc_taxtable, QOF_TYPE_INSTANCE)
216
217static void
218gnc_taxtable_init(GncTaxTable* tt)
219{
220}
221
222static void
223gnc_taxtable_dispose(GObject *ttp)
224{
225 G_OBJECT_CLASS(gnc_taxtable_parent_class)->dispose(ttp);
226}
227
228static void
229gnc_taxtable_finalize(GObject* ttp)
230{
231 G_OBJECT_CLASS(gnc_taxtable_parent_class)->finalize(ttp);
232}
233
234static void
235gnc_taxtable_get_property (GObject *object,
236 guint prop_id,
237 GValue *value,
238 GParamSpec *pspec)
239{
240 GncTaxTable *tt;
241
242 g_return_if_fail(GNC_IS_TAXTABLE(object));
243
244 tt = GNC_TAXTABLE(object);
245 switch (prop_id)
246 {
247 case PROP_NAME:
248 g_value_set_string(value, tt->name);
249 break;
250 case PROP_INVISIBLE:
251 g_value_set_boolean(value, tt->invisible);
252 break;
253 case PROP_REFCOUNT:
254 g_value_set_uint64(value, tt->refcount);
255 break;
256 default:
257 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
258 break;
259 }
260}
261
262static void
263gnc_taxtable_set_property (GObject *object,
264 guint prop_id,
265 const GValue *value,
266 GParamSpec *pspec)
267{
268 GncTaxTable *tt;
269
270 g_return_if_fail(GNC_IS_TAXTABLE(object));
271
272 tt = GNC_TAXTABLE(object);
273 g_assert (qof_instance_get_editlevel(tt));
274
275 switch (prop_id)
276 {
277 case PROP_NAME:
278 gncTaxTableSetName(tt, g_value_get_string(value));
279 break;
280 case PROP_INVISIBLE:
281 if (g_value_get_boolean(value))
282 {
283 gncTaxTableMakeInvisible(tt);
284 }
285 break;
286 case PROP_REFCOUNT:
287 gncTaxTableSetRefcount(tt, g_value_get_uint64(value));
288 break;
289 default:
290 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
291 break;
292 }
293}
294
296static gchar*
297impl_get_display_name(const QofInstance* inst)
298{
299 GncTaxTable* tt;
300
301 g_return_val_if_fail(inst != NULL, FALSE);
302 g_return_val_if_fail(GNC_IS_TAXTABLE(inst), FALSE);
303
304 tt = GNC_TAXTABLE(inst);
305 return g_strdup_printf("Tax table %s", tt->name);
306}
307
309static gboolean
310impl_refers_to_object(const QofInstance* inst, const QofInstance* ref)
311{
312 GncTaxTable* tt;
313
314 g_return_val_if_fail(inst != NULL, FALSE);
315 g_return_val_if_fail(GNC_IS_TAXTABLE(inst), FALSE);
316
317 tt = GNC_TAXTABLE(inst);
318
319 if (GNC_IS_ACCOUNT(ref))
320 {
321 GList* node;
322
323 for (node = tt->entries; node != NULL; node = node->next)
324 {
325 GncTaxTableEntry* tte = node->data;
326
327 if (tte->account == GNC_ACCOUNT(ref))
328 {
329 return TRUE;
330 }
331 }
332 }
333
334 return FALSE;
335}
336
343static GList*
344impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
345{
346 if (!GNC_IS_ACCOUNT(ref))
347 {
348 return NULL;
349 }
350
352}
353
354static void
355gnc_taxtable_class_init (GncTaxTableClass *klass)
356{
357 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
358 QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
359
360 gobject_class->dispose = gnc_taxtable_dispose;
361 gobject_class->finalize = gnc_taxtable_finalize;
362 gobject_class->set_property = gnc_taxtable_set_property;
363 gobject_class->get_property = gnc_taxtable_get_property;
364
365 qof_class->get_display_name = impl_get_display_name;
366 qof_class->refers_to_object = impl_refers_to_object;
367 qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
368
369 g_object_class_install_property
370 (gobject_class,
371 PROP_NAME,
372 g_param_spec_string ("name",
373 "TaxTable Name",
374 "The accountName is an arbitrary string "
375 "assigned by the user. It is intended to "
376 "a short, 10 to 30 character long string "
377 "that is displayed by the GUI as the "
378 "tax table mnemonic.",
379 NULL,
380 G_PARAM_READWRITE));
381
382 g_object_class_install_property
383 (gobject_class,
384 PROP_INVISIBLE,
385 g_param_spec_boolean ("invisible",
386 "Invisible",
387 "TRUE if the tax table is invisible. FALSE if visible.",
388 FALSE,
389 G_PARAM_READWRITE));
390
391 g_object_class_install_property
392 (gobject_class,
393 PROP_REFCOUNT,
394 g_param_spec_uint64("ref-count",
395 "Reference count",
396 "The ref-count property contains number of times this tax table "
397 "is referenced.",
398 0, /* min */
399 G_MAXUINT64, /* max */
400 0, /* default */
401 G_PARAM_READWRITE));
402}
403
404/* Create/Destroy Functions */
406gncTaxTableCreate (QofBook *book)
407{
409 if (!book) return NULL;
410
411 table = g_object_new (GNC_TYPE_TAXTABLE, NULL);
412 qof_instance_init_data (&table->inst, _GNC_MOD_NAME, book);
413 table->name = CACHE_INSERT ("");
414 addObj (table);
415 qof_event_gen (&table->inst, QOF_EVENT_CREATE, NULL);
416 return table;
417}
418
419void
420gncTaxTableDestroy (GncTaxTable *table)
421{
422 if (!table) return;
423 qof_instance_set_destroying(table, TRUE);
424 qof_instance_set_dirty (&table->inst);
425 gncTaxTableCommitEdit (table);
426}
427
428static void
429gncTaxTableFree (GncTaxTable *table)
430{
431 GList *list;
432 GncTaxTable *child;
433
434 if (!table) return;
435
436 qof_event_gen (&table->inst, QOF_EVENT_DESTROY, NULL);
437 CACHE_REMOVE (table->name);
438 remObj (table);
439
440 /* destroy the list of entries */
441 for (list = table->entries; list; list = list->next)
442 gncTaxTableEntryDestroy (list->data);
443 g_list_free (table->entries);
444
446 PERR("free a taxtable without do_free set!");
447
448 /* disconnect from parent */
449 if (table->parent)
450 gncTaxTableRemoveChild(table->parent, table);
451
452 /* disconnect from the children */
453 for (list = table->children; list; list = list->next)
454 {
455 child = list->data;
456 gncTaxTableSetParent(child, NULL);
457 }
458 g_list_free(table->children);
459
460 /* qof_instance_release (&table->inst); */
461 g_object_unref (table);
462}
463
464/* =============================================================== */
465
466GncTaxTableEntry * gncTaxTableEntryCreate (void)
467{
468 GncTaxTableEntry *entry;
469 entry = g_new0 (GncTaxTableEntry, 1);
470 entry->amount = gnc_numeric_zero ();
471 return entry;
472}
473
474void gncTaxTableEntryDestroy (GncTaxTableEntry *entry)
475{
476 if (!entry) return;
477 g_free (entry);
478}
479
480/* =============================================================== */
481/* Set Functions */
482
483void gncTaxTableSetName (GncTaxTable *table, const char *name)
484{
485 if (!table || !name) return;
486 SET_STR (table, table->name, name);
487 mark_table (table);
488 maybe_resort_list (table);
489 gncTaxTableCommitEdit (table);
490}
491
492void gncTaxTableSetParent (GncTaxTable *table, GncTaxTable *parent)
493{
494 if (!table) return;
495 gncTaxTableBeginEdit (table);
496 if (table->parent)
497 gncTaxTableRemoveChild(table->parent, table);
498 table->parent = parent;
499 if (parent)
500 gncTaxTableAddChild(parent, table);
501 table->refcount = 0;
502 gncTaxTableMakeInvisible (table);
503 mark_table (table);
504 gncTaxTableCommitEdit (table);
505}
506
507void gncTaxTableSetChild (GncTaxTable *table, GncTaxTable *child)
508{
509 if (!table) return;
510 gncTaxTableBeginEdit (table);
511 table->child = child;
512 mark_table (table);
513 gncTaxTableCommitEdit (table);
514}
515
516void gncTaxTableIncRef (GncTaxTable *table)
517{
518 if (!table) return;
519 if (table->parent || table->invisible) return; /* children dont need refcounts */
520 gncTaxTableBeginEdit (table);
521 table->refcount++;
522 mark_table (table);
523 gncTaxTableCommitEdit (table);
524}
525
526void gncTaxTableDecRef (GncTaxTable *table)
527{
528 if (!table) return;
529 if (table->parent || table->invisible) return; /* children dont need refcounts */
530 g_return_if_fail (table->refcount > 0);
531 gncTaxTableBeginEdit (table);
532 table->refcount--;
533 mark_table (table);
534 gncTaxTableCommitEdit (table);
535}
536
537void gncTaxTableSetRefcount (GncTaxTable *table, gint64 refcount)
538{
539 if (!table) return;
540 g_return_if_fail (refcount >= 0);
541 gncTaxTableBeginEdit (table);
542 table->refcount = refcount;
543 mark_table (table);
544 gncTaxTableCommitEdit (table);
545}
546
547void gncTaxTableMakeInvisible (GncTaxTable *table)
548{
549 struct _book_info *bi;
550 if (!table) return;
551 gncTaxTableBeginEdit (table);
552 table->invisible = TRUE;
553 bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
554 bi->tables = g_list_remove (bi->tables, table);
555 gncTaxTableCommitEdit (table);
556}
557
558void gncTaxTableEntrySetAccount (GncTaxTableEntry *entry, Account *account)
559{
560 if (!entry || !account) return;
561 if (entry->account == account) return;
562 entry->account = account;
563 if (entry->table)
564 {
565 mark_table (entry->table);
566 mod_table (entry->table);
567 }
568}
569
570void gncTaxTableEntrySetType (GncTaxTableEntry *entry, GncAmountType type)
571{
572 if (!entry) return;
573 if (entry->type == type) return;
574 entry->type = type;
575 if (entry->table)
576 {
577 mark_table (entry->table);
578 mod_table (entry->table);
579 }
580}
581
582void gncTaxTableEntrySetAmount (GncTaxTableEntry *entry, gnc_numeric amount)
583{
584 if (!entry) return;
585 if (gnc_numeric_eq (entry->amount, amount)) return;
586 entry->amount = amount;
587 if (entry->table)
588 {
589 mark_table (entry->table);
590 mod_table (entry->table);
591 }
592}
593
594void gncTaxTableAddEntry (GncTaxTable *table, GncTaxTableEntry *entry)
595{
596 if (!table || !entry) return;
597 if (entry->table == table) return; /* already mine */
598
599 gncTaxTableBeginEdit (table);
600 if (entry->table)
601 gncTaxTableRemoveEntry (entry->table, entry);
602
603 entry->table = table;
604 table->entries = g_list_insert_sorted (table->entries, entry,
605 (GCompareFunc)gncTaxTableEntryCompare);
606 mark_table (table);
607 mod_table (table);
608 gncTaxTableCommitEdit (table);
609}
610
611void gncTaxTableRemoveEntry (GncTaxTable *table, GncTaxTableEntry *entry)
612{
613 if (!table || !entry) return;
614 gncTaxTableBeginEdit (table);
615 entry->table = NULL;
616 table->entries = g_list_remove (table->entries, entry);
617 mark_table (table);
618 mod_table (table);
619 gncTaxTableCommitEdit (table);
620}
621
622void gncTaxTableChanged (GncTaxTable *table)
623{
624 if (!table) return;
625 gncTaxTableBeginEdit (table);
626 table->child = NULL;
627 gncTaxTableCommitEdit (table);
628}
629
630/* =============================================================== */
631
632void gncTaxTableBeginEdit (GncTaxTable *table)
633{
634 qof_begin_edit(&table->inst);
635}
636
637static void gncTaxTableOnError (QofInstance *inst, QofBackendError errcode)
638{
639 PERR("TaxTable QofBackend Failure: %d", errcode);
640 gnc_engine_signal_commit_error( errcode );
641}
642
643static void gncTaxTableOnDone (QofInstance *inst) {}
644
645static void table_free (QofInstance *inst)
646{
647 GncTaxTable *table = (GncTaxTable *) inst;
648 gncTaxTableFree (table);
649}
650
651void gncTaxTableCommitEdit (GncTaxTable *table)
652{
653 /* GnuCash 2.6.3 and earlier didn't handle taxtable kvp's... */
654 if (qof_instance_has_kvp (QOF_INSTANCE (table)))
656 GNC_FEATURE_KVP_EXTRA_DATA);
657
658 if (!qof_commit_edit (QOF_INSTANCE(table))) return;
659 qof_commit_edit_part2 (&table->inst, gncTaxTableOnError,
660 gncTaxTableOnDone, table_free);
661}
662
663
664/* =============================================================== */
665/* Get Functions */
666
667GncTaxTable *gncTaxTableLookupByName (QofBook *book, const char *name)
668{
669 GList *list = gncTaxTableGetTables (book);
670
671 for ( ; list; list = list->next)
672 {
673 GncTaxTable *table = list->data;
674 if (!g_strcmp0 (table->name, name))
675 return list->data;
676 }
677 return NULL;
678}
679
681gncTaxTableGetDefault (QofBook *book, GncOwnerType type)
682{
683 GSList *path = NULL;
684 const GncGUID *guid = NULL;
685 const char *vendor = "Default Vendor TaxTable";
686 const char *customer = "Default Customer TaxTable";
687 const char *section = "Business";
688
689 g_return_val_if_fail (book != NULL, NULL);
690 g_return_val_if_fail (type == GNC_OWNER_CUSTOMER || \
691 type == GNC_OWNER_VENDOR, NULL);
692 path = g_slist_prepend (path, type == GNC_OWNER_CUSTOMER ? (void*)customer : (void*)vendor);
693 path = g_slist_prepend (path, (void*)section);
694
695 guid = qof_book_get_guid_option (book, path);
696 g_slist_free (path);
697
698 return gncTaxTableLookup (book, guid);
699}
700
701GncTaxTableList * gncTaxTableGetTables (QofBook *book)
702{
703 struct _book_info *bi;
704 if (!book) return NULL;
705
706 bi = qof_book_get_data (book, _GNC_MOD_NAME);
707 return bi ? bi->tables : NULL;
708}
709
710const char *gncTaxTableGetName (const GncTaxTable *table)
711{
712 if (!table) return NULL;
713 return table->name;
714}
715
716static GncTaxTableEntry *gncTaxTableEntryCopy (const GncTaxTableEntry *entry)
717{
719 if (!entry) return NULL;
720
721 e = gncTaxTableEntryCreate ();
722 gncTaxTableEntrySetAccount (e, entry->account);
723 gncTaxTableEntrySetType (e, entry->type);
724 gncTaxTableEntrySetAmount (e, entry->amount);
725
726 return e;
727}
728
729static GncTaxTable *gncTaxTableCopy (const GncTaxTable *table)
730{
731 GncTaxTable *t;
732 GList *list;
733
734 if (!table) return NULL;
735 t = gncTaxTableCreate (qof_instance_get_book(table));
736 gncTaxTableSetName (t, table->name);
737 for (list = table->entries; list; list = list->next)
738 {
739 GncTaxTableEntry *entry, *e;
740 entry = list->data;
741 e = gncTaxTableEntryCopy (entry);
742 /* Clang static analyzer thinks we're leaking e, but we're not.
743 * We're transferring it to table. */
744 gncTaxTableAddEntry (t, e);
745 }
746 return t;
747}
748
749GncTaxTable *gncTaxTableReturnChild (GncTaxTable *table, gboolean make_new)
750{
751 GncTaxTable *child = NULL;
752
753 if (!table) return NULL;
754 if (table->child) return table->child;
755 if (table->parent || table->invisible) return table;
756 if (make_new)
757 {
758 child = gncTaxTableCopy (table);
759 gncTaxTableSetChild (table, child);
760 gncTaxTableSetParent (child, table);
761 }
762 return child;
763}
764
765GncTaxTable *gncTaxTableGetParent (const GncTaxTable *table)
766{
767 if (!table) return NULL;
768 return table->parent;
769}
770
771GncTaxTableEntryList* gncTaxTableGetEntries (const GncTaxTable *table)
772{
773 if (!table) return NULL;
774 return table->entries;
775}
776
777gint64 gncTaxTableGetRefcount (const GncTaxTable *table)
778{
779 if (!table) return 0;
780 return table->refcount;
781}
782
783time64 gncTaxTableLastModifiedSecs (const GncTaxTable *table)
784{
785 if (!table) return 0;
786 return table->modtime;
787}
788
789gboolean gncTaxTableGetInvisible (const GncTaxTable *table)
790{
791 if (!table) return FALSE;
792 return table->invisible;
793}
794
795Account * gncTaxTableEntryGetAccount (const GncTaxTableEntry *entry)
796{
797 if (!entry) return NULL;
798 return entry->account;
799}
800
801GncAmountType gncTaxTableEntryGetType (const GncTaxTableEntry *entry)
802{
803 if (!entry) return 0;
804 return entry->type;
805}
806
807gnc_numeric gncTaxTableEntryGetAmount (const GncTaxTableEntry *entry)
808{
809 if (!entry) return gnc_numeric_zero();
810 return entry->amount;
811}
812
813/* This is a semi-private function (meaning that it's not declared in
814 * the header) used for SQL Backend testing. */
815GncTaxTable* gncTaxTableEntryGetTable( const GncTaxTableEntry* entry )
816{
817 if (!entry) return NULL;
818 return entry->table;
819}
820
821int gncTaxTableEntryCompare (const GncTaxTableEntry *a, const GncTaxTableEntry *b)
822{
823 char *name_a, *name_b;
824 int retval;
825
826 if (!a && !b) return 0;
827 if (!a) return -1;
828 if (!b) return 1;
829
830 name_a = gnc_account_get_full_name (a->account);
831 name_b = gnc_account_get_full_name (b->account);
832 retval = g_strcmp0(name_a, name_b);
833 g_free(name_a);
834 g_free(name_b);
835
836 if (retval)
837 return retval;
838
839 return gnc_numeric_compare (a->amount, b->amount);
840}
841
842int gncTaxTableCompare (const GncTaxTable *a, const GncTaxTable *b)
843{
844 if (!a && !b) return 0;
845 if (!a) return -1;
846 if (!b) return 1;
847 return g_strcmp0 (a->name, b->name);
848}
849
850gboolean gncTaxTableEntryEqual(const GncTaxTableEntry *a, const GncTaxTableEntry *b)
851{
852 if (a == NULL && b == NULL) return TRUE;
853 if (a == NULL || b == NULL) return FALSE;
854
855 if (!xaccAccountEqual(a->account, b->account, TRUE))
856 {
857 PWARN("accounts differ");
858 return FALSE;
859 }
860
861 if (a->type != b->type)
862 {
863 PWARN("types differ");
864 return FALSE;
865 }
866
867 if (!gnc_numeric_equal(a->amount, b->amount))
868 {
869 PWARN("amounts differ");
870 return FALSE;
871 }
872
873 return TRUE;
874}
875
876gboolean gncTaxTableEqual(const GncTaxTable *a, const GncTaxTable *b)
877{
878 if (a == NULL && b == NULL) return TRUE;
879 if (a == NULL || b == NULL) return FALSE;
880
881 g_return_val_if_fail(GNC_IS_TAXTABLE(a), FALSE);
882 g_return_val_if_fail(GNC_IS_TAXTABLE(b), FALSE);
883
884 if (g_strcmp0(a->name, b->name) != 0)
885 {
886 PWARN("Names differ: %s vs %s", a->name, b->name);
887 return FALSE;
888 }
889
890 if (a->invisible != b->invisible)
891 {
892 PWARN("invisible flags differ");
893 return FALSE;
894 }
895
896 if ((a->entries != NULL) != (b->entries != NULL))
897 {
898 PWARN("only one has entries");
899 return FALSE;
900 }
901
902 if (a->entries != NULL && b->entries != NULL)
903 {
904 GncTaxTableEntryList* a_node;
905 GncTaxTableEntryList* b_node;
906
907 for (a_node = a->entries, b_node = b->entries;
908 a_node != NULL && b_node != NULL;
909 a_node = a_node->next, b_node = b_node->next)
910 {
911 if (!gncTaxTableEntryEqual((GncTaxTableEntry*)a_node->data,
912 (GncTaxTableEntry*)b_node->data))
913 {
914 PWARN("entries differ");
915 return FALSE;
916 }
917 }
918
919 if (a_node != NULL || b_node != NULL)
920 {
921 PWARN("Unequal number of entries");
922 return FALSE;
923 }
924 }
925
926#if 0
927 /* See libgnucash/engine/TaxTableBillTermImmutability.txt for an explanation of the following */
928 /* Code that handles this is *identical* to that in gncBillTerm */
929 gint64 refcount;
930 GncTaxTable * parent; /* if non-null, we are an immutable child */
931 GncTaxTable * child; /* if non-null, we have not changed */
932 GList * children; /* list of children for disconnection */
933#endif
934
935 return TRUE;
936}
937
938/*
939 * This will add value to the account-value for acc, creating a new
940 * list object if necessary
941 */
942GList *gncAccountValueAdd (GList *list, Account *acc, gnc_numeric value)
943{
944 GList *li;
945 GncAccountValue *res = NULL;
946
947 g_return_val_if_fail (acc, list);
948 g_return_val_if_fail (gnc_numeric_check (value) == GNC_ERROR_OK, list);
949
950 /* Try to find the account in the list */
951 for (li = list; li; li = li->next)
952 {
953 res = li->data;
954 if (res->account == acc)
955 {
956 res->value = gnc_numeric_add (res->value, value, GNC_DENOM_AUTO,
958 return list;
959 }
960 }
961 /* Nope, didn't find it. */
962
963 res = g_new0 (GncAccountValue, 1);
964 res->account = acc;
965 res->value = value;
966 return g_list_prepend (list, res);
967}
968
969/* Merge l2 into l1. l2 is not touched. */
970GList *gncAccountValueAddList (GList *l1, GList *l2)
971{
972 GList *li;
973
974 for (li = l2; li; li = li->next )
975 {
976 GncAccountValue *val = li->data;
977 l1 = gncAccountValueAdd (l1, val->account, val->value);
978 }
979
980 return l1;
981}
982
983/* return the total for this list */
984gnc_numeric gncAccountValueTotal (GList *list)
985{
986 gnc_numeric total = gnc_numeric_zero ();
987
988 for ( ; list ; list = list->next)
989 {
990 GncAccountValue *val = list->data;
992 }
993 return total;
994}
995
996/* Destroy a list of accountvalues */
997void gncAccountValueDestroy (GList *list)
998{
999 GList *node;
1000 for ( node = list; node ; node = node->next)
1001 g_free (node->data);
1002
1003 g_list_free (list);
1004}
1005
1006/* Package-Private functions */
1007
1008static void _gncTaxTableCreate (QofBook *book)
1009{
1010 struct _book_info *bi;
1011
1012 if (!book) return;
1013
1014 bi = g_new0 (struct _book_info, 1);
1015 qof_book_set_data (book, _GNC_MOD_NAME, bi);
1016}
1017
1018static void
1019destroy_taxtable_on_book_close (QofInstance *ent, gpointer data)
1020{
1021 GncTaxTable *table = GNC_TAXTABLE(ent);
1022
1023 gncTaxTableBeginEdit (table);
1024 gncTaxTableDestroy (table);
1025}
1026
1027static void _gncTaxTableDestroy (QofBook *book)
1028{
1029 struct _book_info *bi;
1030 QofCollection *col;
1031
1032 if (!book) return;
1033
1034 bi = qof_book_get_data (book, _GNC_MOD_NAME);
1035
1036 col = qof_book_get_collection (book, GNC_ID_TAXTABLE);
1037 qof_collection_foreach (col, destroy_taxtable_on_book_close, NULL);
1038
1039 g_list_free (bi->tables);
1040 g_free (bi);
1041}
1042
1043static QofObject gncTaxTableDesc =
1044{
1045 DI(.interface_version = ) QOF_OBJECT_VERSION,
1046 DI(.e_type = ) _GNC_MOD_NAME,
1047 DI(.type_label = ) "Tax Table",
1048 DI(.create = ) (gpointer)gncTaxTableCreate,
1049 DI(.book_begin = ) _gncTaxTableCreate,
1050 DI(.book_end = ) _gncTaxTableDestroy,
1051 DI(.is_dirty = ) qof_collection_is_dirty,
1052 DI(.mark_clean = ) qof_collection_mark_clean,
1053 DI(.foreach = ) qof_collection_foreach,
1054 DI(.printable = ) NULL,
1055 DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
1056};
1057
1058gboolean gncTaxTableRegister (void)
1059{
1060 static QofParam params[] =
1061 {
1062 { GNC_TT_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncTaxTableGetName, (QofSetterFunc)gncTaxTableSetName },
1063 { GNC_TT_REFCOUNT, QOF_TYPE_INT64, (QofAccessFunc)gncTaxTableGetRefcount, (QofSetterFunc)gncTaxTableSetRefcount },
1064 { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
1065 { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
1066 { NULL },
1067 };
1068
1069 qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncTaxTableCompare, params);
1070
1071 return qof_object_register (&gncTaxTableDesc);
1072}
1073
1074/* need a QOF tax table entry object */
1075//gncTaxTableEntrySetType_q int32
1076//gint gncTaxTableEntryGetType_q (GncTaxTableEntry *entry);
Utility functions for file access.
gchar * gnc_account_get_full_name(const Account *account)
The gnc_account_get_full_name routine returns the fully qualified name of the account using the given...
Definition Account.cpp:3305
gboolean xaccAccountEqual(const Account *aa, const Account *ab, gboolean check_guids)
Compare two accounts for equality - this is a deep compare.
Definition Account.cpp:1666
QofBackendError
The errors that can be reported to the GUI & other front-end users.
Definition qofbackend.h:58
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
Definition qofbook.cpp:521
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
The QofAccessFunc defines an arbitrary function pointer for access functions.
Definition qofclass.h:123
void(* QofSetterFunc)(gpointer, gpointer)
The QofSetterFunc defines an function pointer for parameter setters.
Definition qofclass.h:130
void qof_class_register(QofIdTypeConst obj_name, QofSortFunc default_sort_function, const QofParam *params)
This function registers a new object class with the Qof subsystem.
Definition qofclass.cpp:86
int(* QofSortFunc)(gconstpointer, gconstpointer)
This function is the default sort function for a particular object type.
Definition qofclass.h:168
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition gnc-date.h:87
time64 gnc_time(time64 *tbuf)
get the current time
Definition gnc-date.cpp:262
gboolean qof_collection_is_dirty(const QofCollection *col)
Return value of 'dirty' flag on collection.
Definition qofid.cpp:232
void qof_event_gen(QofInstance *entity, QofEventId event_id, gpointer event_data)
Invoke all registered event handlers using the given arguments.
Definition qofevent.cpp:231
QofBook * qof_instance_get_book(gconstpointer inst)
Return the book pointer.
const GncGUID * qof_instance_get_guid(gconstpointer inst)
Return the GncGUID of this instance.
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
Compare two instances, based on their last update times.
QofCollection * qof_instance_get_collection(gconstpointer ptr)
Return the collection this instance belongs to.
void qof_instance_init_data(QofInstance *inst, QofIdType type, QofBook *book)
Initialise the settings associated with an instance.
gboolean qof_instance_get_destroying(gconstpointer ptr)
Retrieve the flag that indicates whether or not this object is about to be destroyed.
GList * qof_instance_get_referring_object_list_from_collection(const QofCollection *coll, const QofInstance *ref)
Returns a list of objects from the collection which refer to the specific object.
gboolean qof_instance_has_kvp(QofInstance *inst)
Report whether a QofInstance has anything stored in KVP.
#define PERR(format, args...)
Log a serious error.
Definition qoflog.h:244
#define PWARN(format, args...)
Log a warning.
Definition qoflog.h:250
gboolean gnc_numeric_eq(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b are exactly the same (have the same numerator and ...
#define GNC_DENOM_AUTO
Values that can be passed as the 'denom' argument.
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.
int gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
Returns 1 if a>b, -1 if b>a, 0 if a == b
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b represent the same number.
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Return a+b.
@ GNC_ERROR_OK
No error.
@ GNC_HOW_RND_ROUND_HALF_UP
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
@ GNC_HOW_DENOM_REDUCE
Reduce the result value by common factor elimination, using the smallest possible value for the denom...
void qof_collection_mark_clean(QofCollection *)
reset value of dirty flag
Definition qofid.cpp:238
#define QOF_OBJECT_VERSION
Defines the version of the core object object registration interface.
Definition qofobject.h:63
gboolean qof_object_register(const QofObject *object)
Register new types of object objects.
#define QOF_PARAM_BOOK
"Known" Object Parameters – all objects must support these
Definition qofquery.h:108
void gncAccountValueDestroy(GList *list)
Destroy a list of accountvalues.
GList * gncAccountValueAdd(GList *list, Account *acc, gnc_numeric value)
This will add value to the account-value for acc, creating a new list object if necessary.
#define GNC_TT_NAME
QOF parameter definitions.
GncAmountType
How to interpret the amount.
Definition gncTaxTable.h:79
GncTaxIncluded
How to interpret the TaxIncluded.
Definition gncTaxTable.h:86
GList * gncAccountValueAddList(GList *l1, GList *l2)
Merge l2 into l1.
gnc_numeric gncAccountValueTotal(GList *list)
return the total for this list
void gnc_features_set_used(QofBook *book, const gchar *feature)
Indicate that the current book uses the given feature.
gboolean qof_commit_edit_part2(QofInstance *inst, void(*on_error)(QofInstance *, QofBackendError), void(*on_done)(QofInstance *), void(*on_free)(QofInstance *))
part2 – deal with the backend
gboolean qof_commit_edit(QofInstance *inst)
commit_edit helpers
gboolean qof_begin_edit(QofInstance *inst)
begin_edit
STRUCTS.
The type used to store guids in C.
Definition guid.h:75
modtime is the internal date of the last modtime See libgnucash/engine/TaxTableBillTermImmutability....
QofBook reference.
Definition qofbook-p.hpp:47