GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 [email protected] *
20  * *
21 \********************************************************************/
22 
23 /*
24  * Copyright (C) 2002 Derek Atkins
25  * Copyright (C) 2003 Linas Vepstas <[email protected]>
26  * Author: Derek Atkins <[email protected]>
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  char * name;
41  GncTaxTableEntryList* entries;
42  Timespec modtime; /* internal date of last modtime */
43 
44  /* See src/doc/business.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 
66 struct _book_info
67 {
68  GList * tables; /* visible tables */
69 };
70 
71 static 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);
78 const char *
79 gncAmountTypeToString (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 
92 const char *
93 gncTaxIncludedTypeToString (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); }
109 gboolean
110 gncAmountStringToType (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 
120 gboolean
121 gncTaxIncludedStringToType (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  char * tmp; \
140  \
141  if (!g_strcmp0 (member, str)) return; \
142  gncTaxTableBeginEdit (obj); \
143  tmp = CACHE_INSERT (str); \
144  CACHE_REMOVE (member); \
145  member = tmp; \
146  }
147 
148 static inline void
149 mark_table (GncTaxTable *table)
150 {
151  qof_instance_set_dirty(&table->inst);
152  qof_event_gen (&table->inst, QOF_EVENT_MODIFY, NULL);
153 }
154 
155 static inline void
156 maybe_resort_list (GncTaxTable *table)
157 {
158  struct _book_info *bi;
159 
160  if (table->parent || table->invisible) return;
161  bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
162  bi->tables = g_list_sort (bi->tables, (GCompareFunc)gncTaxTableCompare);
163 }
164 
165 static inline void
166 mod_table (GncTaxTable *table)
167 {
168  timespecFromTime64 (&table->modtime, gnc_time (NULL));
169 }
170 
171 static inline void addObj (GncTaxTable *table)
172 {
173  struct _book_info *bi;
174  bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
175  bi->tables = g_list_insert_sorted (bi->tables, table,
176  (GCompareFunc)gncTaxTableCompare);
177 }
178 
179 static inline void remObj (GncTaxTable *table)
180 {
181  struct _book_info *bi;
182  bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
183  bi->tables = g_list_remove (bi->tables, table);
184 }
185 
186 static inline void
187 gncTaxTableAddChild (GncTaxTable *table, GncTaxTable *child)
188 {
189  g_return_if_fail(table);
190  g_return_if_fail(child);
191  g_return_if_fail(qof_instance_get_destroying(table) == FALSE);
192 
193  table->children = g_list_prepend(table->children, child);
194 }
195 
196 static inline void
197 gncTaxTableRemoveChild (GncTaxTable *table, const GncTaxTable *child)
198 {
199  g_return_if_fail(table);
200  g_return_if_fail(child);
201 
202  if (qof_instance_get_destroying(table)) return;
203 
204  table->children = g_list_remove(table->children, child);
205 }
206 
207 /* =============================================================== */
208 
209 enum
210 {
211  PROP_0,
212  PROP_NAME, /* Table */
213  PROP_INVISIBLE, /* Table */
214  PROP_REFCOUNT, /* Table */
215 // PROP_PARENT, /* Table */
216 };
217 
218 /* GObject Initialization */
219 G_DEFINE_TYPE(GncTaxTable, gnc_taxtable, QOF_TYPE_INSTANCE);
220 
221 static void
222 gnc_taxtable_init(GncTaxTable* tt)
223 {
224 }
225 
226 static void
227 gnc_taxtable_dispose(GObject *ttp)
228 {
229  G_OBJECT_CLASS(gnc_taxtable_parent_class)->dispose(ttp);
230 }
231 
232 static void
233 gnc_taxtable_finalize(GObject* ttp)
234 {
235  G_OBJECT_CLASS(gnc_taxtable_parent_class)->dispose(ttp);
236 }
237 
238 static void
239 gnc_taxtable_get_property (GObject *object,
240  guint prop_id,
241  GValue *value,
242  GParamSpec *pspec)
243 {
244  GncTaxTable *tt;
245 
246  g_return_if_fail(GNC_IS_TAXTABLE(object));
247 
248  tt = GNC_TAXTABLE(object);
249  switch (prop_id)
250  {
251  case PROP_NAME:
252  g_value_set_string(value, tt->name);
253  break;
254  case PROP_INVISIBLE:
255  g_value_set_boolean(value, tt->invisible);
256  break;
257  case PROP_REFCOUNT:
258  g_value_set_uint64(value, tt->refcount);
259  break;
260  default:
261  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
262  break;
263  }
264 }
265 
266 static void
267 gnc_taxtable_set_property (GObject *object,
268  guint prop_id,
269  const GValue *value,
270  GParamSpec *pspec)
271 {
272  GncTaxTable *tt;
273 
274  g_return_if_fail(GNC_IS_TAXTABLE(object));
275 
276  tt = GNC_TAXTABLE(object);
277  g_assert (qof_instance_get_editlevel(tt));
278 
279  switch (prop_id)
280  {
281  case PROP_NAME:
282  gncTaxTableSetName(tt, g_value_get_string(value));
283  break;
284  case PROP_INVISIBLE:
285  if (g_value_get_boolean(value))
286  {
287  gncTaxTableMakeInvisible(tt);
288  }
289  break;
290  case PROP_REFCOUNT:
291  gncTaxTableSetRefcount(tt, g_value_get_uint64(value));
292  break;
293  default:
294  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
295  break;
296  }
297 }
298 
300 static gchar*
301 impl_get_display_name(const QofInstance* inst)
302 {
303  GncTaxTable* tt;
304 
305  g_return_val_if_fail(inst != NULL, FALSE);
306  g_return_val_if_fail(GNC_IS_TAXTABLE(inst), FALSE);
307 
308  tt = GNC_TAXTABLE(inst);
309  return g_strdup_printf("Tax table %s", tt->name);
310 }
311 
313 static gboolean
314 impl_refers_to_object(const QofInstance* inst, const QofInstance* ref)
315 {
316  GncTaxTable* tt;
317 
318  g_return_val_if_fail(inst != NULL, FALSE);
319  g_return_val_if_fail(GNC_IS_TAXTABLE(inst), FALSE);
320 
321  tt = GNC_TAXTABLE(inst);
322 
323  if (GNC_IS_ACCOUNT(ref))
324  {
325  GList* node;
326 
327  for (node = tt->entries; node != NULL; node = node->next)
328  {
329  GncTaxTableEntry* tte = node->data;
330 
331  if (tte->account == GNC_ACCOUNT(ref))
332  {
333  return TRUE;
334  }
335  }
336  }
337 
338  return FALSE;
339 }
340 
347 static GList*
348 impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
349 {
350  if (!GNC_IS_ACCOUNT(ref))
351  {
352  return NULL;
353  }
354 
356 }
357 
358 static void
359 gnc_taxtable_class_init (GncTaxTableClass *klass)
360 {
361  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
362  QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
363 
364  gobject_class->dispose = gnc_taxtable_dispose;
365  gobject_class->finalize = gnc_taxtable_finalize;
366  gobject_class->set_property = gnc_taxtable_set_property;
367  gobject_class->get_property = gnc_taxtable_get_property;
368 
369  qof_class->get_display_name = impl_get_display_name;
370  qof_class->refers_to_object = impl_refers_to_object;
371  qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
372 
373  g_object_class_install_property
374  (gobject_class,
375  PROP_NAME,
376  g_param_spec_string ("name",
377  "TaxTable Name",
378  "The accountName is an arbitrary string "
379  "assigned by the user. It is intended to "
380  "a short, 10 to 30 character long string "
381  "that is displayed by the GUI as the "
382  "tax table mnemonic.",
383  NULL,
384  G_PARAM_READWRITE));
385 
386  g_object_class_install_property
387  (gobject_class,
388  PROP_INVISIBLE,
389  g_param_spec_boolean ("invisible",
390  "Invisible",
391  "TRUE if the tax table is invisible. FALSE if visible.",
392  FALSE,
393  G_PARAM_READWRITE));
394 
395  g_object_class_install_property
396  (gobject_class,
397  PROP_REFCOUNT,
398  g_param_spec_uint64("ref-count",
399  "Reference count",
400  "The ref-count property contains number of times this tax table "
401  "is referenced.",
402  0, /* min */
403  G_MAXUINT64, /* max */
404  0, /* default */
405  G_PARAM_READWRITE));
406 }
407 
408 /* Create/Destroy Functions */
409 GncTaxTable *
410 gncTaxTableCreate (QofBook *book)
411 {
412  GncTaxTable *table;
413  if (!book) return NULL;
414 
415  table = g_object_new (GNC_TYPE_TAXTABLE, NULL);
416  qof_instance_init_data (&table->inst, _GNC_MOD_NAME, book);
417  table->name = CACHE_INSERT ("");
418  addObj (table);
419  qof_event_gen (&table->inst, QOF_EVENT_CREATE, NULL);
420  return table;
421 }
422 
423 void
424 gncTaxTableDestroy (GncTaxTable *table)
425 {
426  if (!table) return;
427  qof_instance_set_destroying(table, TRUE);
428  qof_instance_set_dirty (&table->inst);
429  gncTaxTableCommitEdit (table);
430 }
431 
432 static void
433 gncTaxTableFree (GncTaxTable *table)
434 {
435  GList *list;
436  GncTaxTable *child;
437 
438  if (!table) return;
439 
440  qof_event_gen (&table->inst, QOF_EVENT_DESTROY, NULL);
441  CACHE_REMOVE (table->name);
442  remObj (table);
443 
444  /* destroy the list of entries */
445  for (list = table->entries; list; list = list->next)
446  gncTaxTableEntryDestroy (list->data);
447  g_list_free (table->entries);
448 
449  if (!qof_instance_get_destroying(table))
450  PERR("free a taxtable without do_free set!");
451 
452  /* disconnect from parent */
453  if (table->parent)
454  gncTaxTableRemoveChild(table->parent, table);
455 
456  /* disconnect from the children */
457  for (list = table->children; list; list = list->next)
458  {
459  child = list->data;
460  gncTaxTableSetParent(child, NULL);
461  }
462  g_list_free(table->children);
463 
464  /* qof_instance_release (&table->inst); */
465  g_object_unref (table);
466 }
467 
468 /* =============================================================== */
469 
470 GncTaxTableEntry * gncTaxTableEntryCreate (void)
471 {
472  GncTaxTableEntry *entry;
473  entry = g_new0 (GncTaxTableEntry, 1);
474  entry->amount = gnc_numeric_zero ();
475  return entry;
476 }
477 
478 void gncTaxTableEntryDestroy (GncTaxTableEntry *entry)
479 {
480  if (!entry) return;
481  g_free (entry);
482 }
483 
484 /* =============================================================== */
485 /* Set Functions */
486 
487 void gncTaxTableSetName (GncTaxTable *table, const char *name)
488 {
489  if (!table || !name) return;
490  SET_STR (table, table->name, name);
491  mark_table (table);
492  maybe_resort_list (table);
493  gncTaxTableCommitEdit (table);
494 }
495 
496 void gncTaxTableSetParent (GncTaxTable *table, GncTaxTable *parent)
497 {
498  if (!table) return;
499  gncTaxTableBeginEdit (table);
500  if (table->parent)
501  gncTaxTableRemoveChild(table->parent, table);
502  table->parent = parent;
503  if (parent)
504  gncTaxTableAddChild(parent, table);
505  table->refcount = 0;
506  gncTaxTableMakeInvisible (table);
507  mark_table (table);
508  gncTaxTableCommitEdit (table);
509 }
510 
511 void gncTaxTableSetChild (GncTaxTable *table, GncTaxTable *child)
512 {
513  if (!table) return;
514  gncTaxTableBeginEdit (table);
515  table->child = child;
516  mark_table (table);
517  gncTaxTableCommitEdit (table);
518 }
519 
520 void gncTaxTableIncRef (GncTaxTable *table)
521 {
522  if (!table) return;
523  if (table->parent || table->invisible) return; /* children dont need refcounts */
524  gncTaxTableBeginEdit (table);
525  table->refcount++;
526  mark_table (table);
527  gncTaxTableCommitEdit (table);
528 }
529 
530 void gncTaxTableDecRef (GncTaxTable *table)
531 {
532  if (!table) return;
533  if (table->parent || table->invisible) return; /* children dont need refcounts */
534  g_return_if_fail (table->refcount > 0);
535  gncTaxTableBeginEdit (table);
536  table->refcount--;
537  mark_table (table);
538  gncTaxTableCommitEdit (table);
539 }
540 
541 void gncTaxTableSetRefcount (GncTaxTable *table, gint64 refcount)
542 {
543  if (!table) return;
544  g_return_if_fail (refcount >= 0);
545  gncTaxTableBeginEdit (table);
546  table->refcount = refcount;
547  mark_table (table);
548  gncTaxTableCommitEdit (table);
549 }
550 
551 void gncTaxTableMakeInvisible (GncTaxTable *table)
552 {
553  struct _book_info *bi;
554  if (!table) return;
555  gncTaxTableBeginEdit (table);
556  table->invisible = TRUE;
557  bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
558  bi->tables = g_list_remove (bi->tables, table);
559  gncTaxTableCommitEdit (table);
560 }
561 
562 void gncTaxTableEntrySetAccount (GncTaxTableEntry *entry, Account *account)
563 {
564  if (!entry || !account) return;
565  if (entry->account == account) return;
566  entry->account = account;
567  if (entry->table)
568  {
569  mark_table (entry->table);
570  mod_table (entry->table);
571  }
572 }
573 
574 void gncTaxTableEntrySetType (GncTaxTableEntry *entry, GncAmountType type)
575 {
576  if (!entry) return;
577  if (entry->type == type) return;
578  entry->type = type;
579  if (entry->table)
580  {
581  mark_table (entry->table);
582  mod_table (entry->table);
583  }
584 }
585 
586 void gncTaxTableEntrySetAmount (GncTaxTableEntry *entry, gnc_numeric amount)
587 {
588  if (!entry) return;
589  if (gnc_numeric_eq (entry->amount, amount)) return;
590  entry->amount = amount;
591  if (entry->table)
592  {
593  mark_table (entry->table);
594  mod_table (entry->table);
595  }
596 }
597 
598 void gncTaxTableAddEntry (GncTaxTable *table, GncTaxTableEntry *entry)
599 {
600  if (!table || !entry) return;
601  if (entry->table == table) return; /* already mine */
602 
603  gncTaxTableBeginEdit (table);
604  if (entry->table)
605  gncTaxTableRemoveEntry (entry->table, entry);
606 
607  entry->table = table;
608  table->entries = g_list_insert_sorted (table->entries, entry,
609  (GCompareFunc)gncTaxTableEntryCompare);
610  mark_table (table);
611  mod_table (table);
612  gncTaxTableCommitEdit (table);
613 }
614 
615 void gncTaxTableRemoveEntry (GncTaxTable *table, GncTaxTableEntry *entry)
616 {
617  if (!table || !entry) return;
618  gncTaxTableBeginEdit (table);
619  entry->table = NULL;
620  table->entries = g_list_remove (table->entries, entry);
621  mark_table (table);
622  mod_table (table);
623  gncTaxTableCommitEdit (table);
624 }
625 
626 void gncTaxTableChanged (GncTaxTable *table)
627 {
628  if (!table) return;
629  gncTaxTableBeginEdit (table);
630  table->child = NULL;
631  gncTaxTableCommitEdit (table);
632 }
633 
634 /* =============================================================== */
635 
636 void gncTaxTableBeginEdit (GncTaxTable *table)
637 {
638  qof_begin_edit(&table->inst);
639 }
640 
641 static void gncTaxTableOnError (QofInstance *inst, QofBackendError errcode)
642 {
643  PERR("TaxTable QofBackend Failure: %d", errcode);
644  gnc_engine_signal_commit_error( errcode );
645 }
646 
647 static void gncTaxTableOnDone (QofInstance *inst) {}
648 
649 static void table_free (QofInstance *inst)
650 {
651  GncTaxTable *table = (GncTaxTable *) inst;
652  gncTaxTableFree (table);
653 }
654 
655 void gncTaxTableCommitEdit (GncTaxTable *table)
656 {
657  /* GnuCash 2.6.3 and earlier didn't handle taxtable kvp's... */
658  if (!kvp_frame_is_empty (table->inst.kvp_data))
659  gnc_features_set_used (qof_instance_get_book (QOF_INSTANCE (table)), GNC_FEATURE_KVP_EXTRA_DATA);
660 
661  if (!qof_commit_edit (QOF_INSTANCE(table))) return;
662  qof_commit_edit_part2 (&table->inst, gncTaxTableOnError,
663  gncTaxTableOnDone, table_free);
664 }
665 
666 
667 /* =============================================================== */
668 /* Get Functions */
669 
670 GncTaxTable *gncTaxTableLookupByName (QofBook *book, const char *name)
671 {
672  GList *list = gncTaxTableGetTables (book);
673 
674  for ( ; list; list = list->next)
675  {
676  GncTaxTable *table = list->data;
677  if (!g_strcmp0 (table->name, name))
678  return list->data;
679  }
680  return NULL;
681 }
682 
683 GList * gncTaxTableGetTables (QofBook *book)
684 {
685  struct _book_info *bi;
686  if (!book) return NULL;
687 
688  bi = qof_book_get_data (book, _GNC_MOD_NAME);
689  return bi->tables;
690 }
691 
692 const char *gncTaxTableGetName (const GncTaxTable *table)
693 {
694  if (!table) return NULL;
695  return table->name;
696 }
697 
698 static GncTaxTableEntry *gncTaxTableEntryCopy (const GncTaxTableEntry *entry)
699 {
700  GncTaxTableEntry *e;
701  if (!entry) return NULL;
702 
703  e = gncTaxTableEntryCreate ();
704  gncTaxTableEntrySetAccount (e, entry->account);
705  gncTaxTableEntrySetType (e, entry->type);
706  gncTaxTableEntrySetAmount (e, entry->amount);
707 
708  return e;
709 }
710 
711 static GncTaxTable *gncTaxTableCopy (const GncTaxTable *table)
712 {
713  GncTaxTable *t;
714  GList *list;
715 
716  if (!table) return NULL;
717  t = gncTaxTableCreate (qof_instance_get_book(table));
718  gncTaxTableSetName (t, table->name);
719  for (list = table->entries; list; list = list->next)
720  {
721  GncTaxTableEntry *entry, *e;
722  entry = list->data;
723  e = gncTaxTableEntryCopy (entry);
724  gncTaxTableAddEntry (t, e);
725  }
726  return t;
727 }
728 
729 GncTaxTable *gncTaxTableReturnChild (GncTaxTable *table, gboolean make_new)
730 {
731  GncTaxTable *child = NULL;
732 
733  if (!table) return NULL;
734  if (table->child) return table->child;
735  if (table->parent || table->invisible) return table;
736  if (make_new)
737  {
738  child = gncTaxTableCopy (table);
739  gncTaxTableSetChild (table, child);
740  gncTaxTableSetParent (child, table);
741  }
742  return child;
743 }
744 
745 GncTaxTable *gncTaxTableGetParent (const GncTaxTable *table)
746 {
747  if (!table) return NULL;
748  return table->parent;
749 }
750 
751 GncTaxTableEntryList* gncTaxTableGetEntries (const GncTaxTable *table)
752 {
753  if (!table) return NULL;
754  return table->entries;
755 }
756 
757 gint64 gncTaxTableGetRefcount (const GncTaxTable *table)
758 {
759  if (!table) return 0;
760  return table->refcount;
761 }
762 
763 Timespec gncTaxTableLastModified (const GncTaxTable *table)
764 {
765  Timespec ts = { 0 , 0 };
766  if (!table) return ts;
767  return table->modtime;
768 }
769 
770 gboolean gncTaxTableGetInvisible (const GncTaxTable *table)
771 {
772  if (!table) return FALSE;
773  return table->invisible;
774 }
775 
776 Account * gncTaxTableEntryGetAccount (const GncTaxTableEntry *entry)
777 {
778  if (!entry) return NULL;
779  return entry->account;
780 }
781 
782 GncAmountType gncTaxTableEntryGetType (const GncTaxTableEntry *entry)
783 {
784  if (!entry) return 0;
785  return entry->type;
786 }
787 
788 gnc_numeric gncTaxTableEntryGetAmount (const GncTaxTableEntry *entry)
789 {
790  if (!entry) return gnc_numeric_zero();
791  return entry->amount;
792 }
793 
794 /* This is a semi-private function (meaning that it's not declared in
795  * the header) used for SQL Backend testing. */
796 GncTaxTable* gncTaxTableEntryGetTable( const GncTaxTableEntry* entry )
797 {
798  if (!entry) return NULL;
799  return entry->table;
800 }
801 
802 int gncTaxTableEntryCompare (const GncTaxTableEntry *a, const GncTaxTableEntry *b)
803 {
804  char *name_a, *name_b;
805  int retval;
806 
807  if (!a && !b) return 0;
808  if (!a) return -1;
809  if (!b) return 1;
810 
811  name_a = gnc_account_get_full_name (a->account);
812  name_b = gnc_account_get_full_name (b->account);
813  retval = g_strcmp0(name_a, name_b);
814  g_free(name_a);
815  g_free(name_b);
816 
817  if (retval)
818  return retval;
819 
820  return gnc_numeric_compare (a->amount, b->amount);
821 }
822 
823 int gncTaxTableCompare (const GncTaxTable *a, const GncTaxTable *b)
824 {
825  if (!a && !b) return 0;
826  if (!a) return -1;
827  if (!b) return 1;
828  return g_strcmp0 (a->name, b->name);
829 }
830 
831 gboolean gncTaxTableEntryEqual(const GncTaxTableEntry *a, const GncTaxTableEntry *b)
832 {
833  if (a == NULL && b == NULL) return TRUE;
834  if (a == NULL || b == NULL) return FALSE;
835 
836  if (!xaccAccountEqual(a->account, b->account, TRUE))
837  {
838  PWARN("accounts differ");
839  return FALSE;
840  }
841 
842  if (a->type != b->type)
843  {
844  PWARN("types differ");
845  return FALSE;
846  }
847 
848  if (!gnc_numeric_equal(a->amount, b->amount))
849  {
850  PWARN("amounts differ");
851  return FALSE;
852  }
853 
854  return TRUE;
855 }
856 
857 gboolean gncTaxTableEqual(const GncTaxTable *a, const GncTaxTable *b)
858 {
859  if (a == NULL && b == NULL) return TRUE;
860  if (a == NULL || b == NULL) return FALSE;
861 
862  g_return_val_if_fail(GNC_IS_TAXTABLE(a), FALSE);
863  g_return_val_if_fail(GNC_IS_TAXTABLE(b), FALSE);
864 
865  if (g_strcmp0(a->name, b->name) != 0)
866  {
867  PWARN("Names differ: %s vs %s", a->name, b->name);
868  return FALSE;
869  }
870 
871  if (a->invisible != b->invisible)
872  {
873  PWARN("invisible flags differ");
874  return FALSE;
875  }
876 
877  if ((a->entries != NULL) != (b->entries != NULL))
878  {
879  PWARN("only one has entries");
880  return FALSE;
881  }
882 
883  if (a->entries != NULL && b->entries != NULL)
884  {
885  GncTaxTableEntryList* a_node;
886  GncTaxTableEntryList* b_node;
887 
888  for (a_node = a->entries, b_node = b->entries;
889  a_node != NULL && b_node != NULL;
890  a_node = a_node->next, b_node = b_node->next)
891  {
892  if (!gncTaxTableEntryEqual((GncTaxTableEntry*)a_node->data,
893  (GncTaxTableEntry*)b_node->data))
894  {
895  PWARN("entries differ");
896  return FALSE;
897  }
898  }
899 
900  if (a_node != NULL || b_node != NULL)
901  {
902  PWARN("Unequal number of entries");
903  return FALSE;
904  }
905  }
906 
907 #if 0
908  /* See src/doc/business.txt for an explanation of the following */
909  /* Code that handles this is *identical* to that in gncBillTerm */
910  gint64 refcount;
911  GncTaxTable * parent; /* if non-null, we are an immutable child */
912  GncTaxTable * child; /* if non-null, we have not changed */
913  GList * children; /* list of children for disconnection */
914 #endif
915 
916  return TRUE;
917 }
918 
919 /*
920  * This will add value to the account-value for acc, creating a new
921  * list object if necessary
922  */
923 GList *gncAccountValueAdd (GList *list, Account *acc, gnc_numeric value)
924 {
925  GList *li;
926  GncAccountValue *res = NULL;
927 
928  g_return_val_if_fail (acc, list);
929  g_return_val_if_fail (gnc_numeric_check (value) == GNC_ERROR_OK, list);
930 
931  /* Try to find the account in the list */
932  for (li = list; li; li = li->next)
933  {
934  res = li->data;
935  if (res->account == acc)
936  {
937  res->value = gnc_numeric_add (res->value, value, GNC_DENOM_AUTO,
939  return list;
940  }
941  }
942  /* Nope, didn't find it. */
943 
944  res = g_new0 (GncAccountValue, 1);
945  res->account = acc;
946  res->value = value;
947  return g_list_prepend (list, res);
948 }
949 
950 /* Merge l2 into l1. l2 is not touched. */
951 GList *gncAccountValueAddList (GList *l1, GList *l2)
952 {
953  GList *li;
954 
955  for (li = l2; li; li = li->next )
956  {
957  GncAccountValue *val = li->data;
958  l1 = gncAccountValueAdd (l1, val->account, val->value);
959  }
960 
961  return l1;
962 }
963 
964 /* return the total for this list */
966 {
967  gnc_numeric total = gnc_numeric_zero ();
968 
969  for ( ; list ; list = list->next)
970  {
971  GncAccountValue *val = list->data;
972  total = gnc_numeric_add (total, val->value, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
973  }
974  return total;
975 }
976 
977 /* Destroy a list of accountvalues */
978 void gncAccountValueDestroy (GList *list)
979 {
980  GList *node;
981  for ( node = list; node ; node = node->next)
982  g_free (node->data);
983 
984  g_list_free (list);
985 }
986 
987 /* Package-Private functions */
988 
989 static void _gncTaxTableCreate (QofBook *book)
990 {
991  struct _book_info *bi;
992 
993  if (!book) return;
994 
995  bi = g_new0 (struct _book_info, 1);
996  qof_book_set_data (book, _GNC_MOD_NAME, bi);
997 }
998 
999 static void _gncTaxTableDestroy (QofBook *book)
1000 {
1001  struct _book_info *bi;
1002 
1003  if (!book) return;
1004 
1005  bi = qof_book_get_data (book, _GNC_MOD_NAME);
1006 
1007  g_list_free (bi->tables);
1008  g_free (bi);
1009 }
1010 
1011 static QofObject gncTaxTableDesc =
1012 {
1013  DI(.interface_version = ) QOF_OBJECT_VERSION,
1014  DI(.e_type = ) _GNC_MOD_NAME,
1015  DI(.type_label = ) "Tax Table",
1016  DI(.create = ) (gpointer)gncTaxTableCreate,
1017  DI(.book_begin = ) _gncTaxTableCreate,
1018  DI(.book_end = ) _gncTaxTableDestroy,
1019  DI(.is_dirty = ) qof_collection_is_dirty,
1020  DI(.mark_clean = ) qof_collection_mark_clean,
1021  DI(.foreach = ) qof_collection_foreach,
1022  DI(.printable = ) NULL,
1023  DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
1024 };
1025 
1026 gboolean gncTaxTableRegister (void)
1027 {
1028  static QofParam params[] =
1029  {
1030  { GNC_TT_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncTaxTableGetName, (QofSetterFunc)gncTaxTableSetName },
1031  { GNC_TT_REFCOUNT, QOF_TYPE_INT64, (QofAccessFunc)gncTaxTableGetRefcount, (QofSetterFunc)gncTaxTableSetRefcount },
1032  { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
1033  { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
1034  { NULL },
1035  };
1036 
1037  qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncTaxTableCompare, params);
1038 
1039  return qof_object_register (&gncTaxTableDesc);
1040 }
1041 
1042 /* need a QOF tax table entry object */
1043 //gncTaxTableEntrySetType_q int32
1044 //gint gncTaxTableEntryGetType_q (GncTaxTableEntry *entry);
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
const GncGUID * qof_instance_get_guid(gconstpointer)
QofBook * qof_instance_get_book(gconstpointer)
gboolean qof_collection_is_dirty(const QofCollection *col)
GncTaxIncluded
Definition: gncTaxTable.h:100
#define GNC_TT_NAME
Definition: gncTaxTable.h:199
QofBackendError
The errors that can be reported to the GUI & other front-end users.
Definition: qofbackend.h:59
gboolean kvp_frame_is_empty(const KvpFrame *frame)
GList * qof_instance_get_referring_object_list_from_collection(const QofCollection *coll, const QofInstance *ref)
gboolean qof_instance_get_destroying(gconstpointer ptr)
void gnc_features_set_used(QofBook *book, const gchar *feature)
Definition: gnc-features.c:131
void qof_class_register(QofIdTypeConst obj_name, QofSortFunc default_sort_fcn, const QofParam *params)
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Use a 64-bit unsigned int timespec.
Definition: gnc-date.h:299
QofCollection * qof_instance_get_collection(gconstpointer inst)
gnc_numeric gncAccountValueTotal(GList *list)
Definition: gncTaxTable.c:965
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
Definition: qofclass.h:177
gint gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
#define QOF_OBJECT_VERSION
Definition: qofobject.h:64
gboolean qof_commit_edit(QofInstance *inst)
#define PERR(format, args...)
Definition: qoflog.h:237
#define QOF_PARAM_BOOK
Definition: qofquery.h:109
void qof_collection_foreach(const QofCollection *, QofInstanceForeachCB, gpointer user_data)
#define PWARN(format, args...)
Definition: qoflog.h:243
void qof_instance_init_data(QofInstance *, QofIdType, QofBook *)
gboolean qof_begin_edit(QofInstance *inst)
gchar * gnc_account_get_full_name(const Account *account)
Definition: Account.c:3038
int(* QofSortFunc)(gconstpointer, gconstpointer)
Definition: qofclass.h:222
void qof_book_set_data(QofBook *book, const gchar *key, gpointer data)
gboolean qof_commit_edit_part2(QofInstance *inst, void(*on_error)(QofInstance *, QofBackendError), void(*on_done)(QofInstance *), void(*on_free)(QofInstance *))
void qof_collection_mark_clean(QofCollection *)
void gncAccountValueDestroy(GList *list)
Definition: gncTaxTable.c:978
gboolean xaccAccountEqual(const Account *aa, const Account *ab, gboolean check_guids)
Definition: Account.c:1475
gboolean gnc_numeric_eq(gnc_numeric a, gnc_numeric b)
GList * gncAccountValueAddList(GList *l1, GList *l2)
Definition: gncTaxTable.c:951
void(* QofSetterFunc)(gpointer, gpointer)
Definition: qofclass.h:184
time64 gnc_time(time64 *tbuf)
get the current local time
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
gboolean qof_object_register(const QofObject *object)
GList * gncAccountValueAdd(GList *list, Account *acc, gnc_numeric value)
Definition: gncTaxTable.c:923
void qof_event_gen(QofInstance *entity, QofEventId event_type, gpointer event_data)
Invoke all registered event handlers using the given arguments.
#define GNC_DENOM_AUTO
Definition: gnc-numeric.h:246
gpointer qof_book_get_data(const QofBook *book, const gchar *key)
GncAmountType
Definition: gncTaxTable.h:93
const gchar * QofLogModule
Definition: qofid.h:89
void timespecFromTime64(Timespec *ts, time64 t)
Utility functions for file access.