GnuCash 2.4.99
gncTaxTable.c
00001 /********************************************************************\
00002  * gncTaxTable.c -- the Gnucash Tax Table interface                 *
00003  *                                                                  *
00004  * This program is free software; you can redistribute it and/or    *
00005  * modify it under the terms of the GNU General Public License as   *
00006  * published by the Free Software Foundation; either version 2 of   *
00007  * the License, or (at your option) any later version.              *
00008  *                                                                  *
00009  * This program is distributed in the hope that it will be useful,  *
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00012  * GNU General Public License for more details.                     *
00013  *                                                                  *
00014  * You should have received a copy of the GNU General Public License*
00015  * along with this program; if not, contact:                        *
00016  *                                                                  *
00017  * Free Software Foundation           Voice:  +1-617-542-5942       *
00018  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00019  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00020  *                                                                  *
00021 \********************************************************************/
00022 
00023 /*
00024  * Copyright (C) 2002 Derek Atkins
00025  * Copyright (C) 2003 Linas Vepstas <linas@linas.org>
00026  * Author: Derek Atkins <warlord@MIT.EDU>
00027  */
00028 
00029 #include "config.h"
00030 
00031 #include <glib.h>
00032 
00033 #include "gncTaxTableP.h"
00034 
00035 struct _gncTaxTable
00036 {
00037     QofInstance     inst;
00038     char *          name;
00039     GncTaxTableEntryList*  entries;
00040     Timespec        modtime;      /* internal date of last modtime */
00041 
00042     /* See src/doc/business.txt for an explanation of the following */
00043     /* Code that handles this is *identical* to that in gncBillTerm */
00044     gint64          refcount;
00045     GncTaxTable *   parent;       /* if non-null, we are an immutable child */
00046     GncTaxTable *   child;        /* if non-null, we have not changed */
00047     gboolean        invisible;
00048     GList *         children;     /* list of children for disconnection */
00049 };
00050 
00051 struct _gncTaxTableClass
00052 {
00053     QofInstanceClass parent_class;
00054 };
00055 
00056 struct _gncTaxTableEntry
00057 {
00058     GncTaxTable *   table;
00059     Account *       account;
00060     GncAmountType   type;
00061     gnc_numeric     amount;
00062 };
00063 
00064 struct _book_info
00065 {
00066     GList *         tables;          /* visible tables */
00067 };
00068 
00069 static QofLogModule log_module = GNC_MOD_BUSINESS;
00070 
00071 /* =============================================================== */
00072 /* You must edit the functions in this block in tandem.  KEEP THEM IN
00073    SYNC! */
00074 
00075 #define GNC_RETURN_ENUM_AS_STRING(x,s) case (x): return (s);
00076 const char *
00077 gncAmountTypeToString (GncAmountType type)
00078 {
00079     switch (type)
00080     {
00081         GNC_RETURN_ENUM_AS_STRING(GNC_AMT_TYPE_VALUE, "VALUE");
00082         GNC_RETURN_ENUM_AS_STRING(GNC_AMT_TYPE_PERCENT, "PERCENT");
00083     default:
00084         g_warning ("asked to translate unknown amount type %d.\n", type);
00085         break;
00086     }
00087     return(NULL);
00088 }
00089 
00090 const char *
00091 gncTaxIncludedTypeToString (GncTaxIncluded type)
00092 {
00093     switch (type)
00094     {
00095         GNC_RETURN_ENUM_AS_STRING(GNC_TAXINCLUDED_YES, "YES");
00096         GNC_RETURN_ENUM_AS_STRING(GNC_TAXINCLUDED_NO, "NO");
00097         GNC_RETURN_ENUM_AS_STRING(GNC_TAXINCLUDED_USEGLOBAL, "USEGLOBAL");
00098     default:
00099         g_warning ("asked to translate unknown taxincluded type %d.\n", type);
00100         break;
00101     }
00102     return(NULL);
00103 }
00104 #undef GNC_RETURN_ENUM_AS_STRING
00105 #define GNC_RETURN_ON_MATCH(s,x) \
00106   if(safe_strcmp((s), (str)) == 0) { *type = x; return(TRUE); }
00107 gboolean
00108 gncAmountStringToType (const char *str, GncAmountType *type)
00109 {
00110     GNC_RETURN_ON_MATCH ("VALUE", GNC_AMT_TYPE_VALUE);
00111     GNC_RETURN_ON_MATCH ("PERCENT", GNC_AMT_TYPE_PERCENT);
00112     g_warning ("asked to translate unknown amount type string %s.\n",
00113                str ? str : "(null)");
00114 
00115     return(FALSE);
00116 }
00117 
00118 gboolean
00119 gncTaxIncludedStringToType (const char *str, GncTaxIncluded *type)
00120 {
00121     GNC_RETURN_ON_MATCH ("YES", GNC_TAXINCLUDED_YES);
00122     GNC_RETURN_ON_MATCH ("NO", GNC_TAXINCLUDED_NO);
00123     GNC_RETURN_ON_MATCH ("USEGLOBAL", GNC_TAXINCLUDED_USEGLOBAL);
00124     g_warning ("asked to translate unknown taxincluded type string %s.\n",
00125                str ? str : "(null)");
00126 
00127     return(FALSE);
00128 }
00129 #undef GNC_RETURN_ON_MATCH
00130 
00131 /* =============================================================== */
00132 /* Misc inline functions */
00133 
00134 #define _GNC_MOD_NAME        GNC_ID_TAXTABLE
00135 
00136 #define SET_STR(obj, member, str) { \
00137         char * tmp; \
00138         \
00139         if (!safe_strcmp (member, str)) return; \
00140         gncTaxTableBeginEdit (obj); \
00141         tmp = CACHE_INSERT (str); \
00142         CACHE_REMOVE (member); \
00143         member = tmp; \
00144         }
00145 
00146 static inline void
00147 mark_table (GncTaxTable *table)
00148 {
00149     qof_instance_set_dirty(&table->inst);
00150     qof_event_gen (&table->inst, QOF_EVENT_MODIFY, NULL);
00151 }
00152 
00153 static inline void
00154 maybe_resort_list (GncTaxTable *table)
00155 {
00156     struct _book_info *bi;
00157 
00158     if (table->parent || table->invisible) return;
00159     bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
00160     bi->tables = g_list_sort (bi->tables, (GCompareFunc)gncTaxTableCompare);
00161 }
00162 
00163 static inline void
00164 mod_table (GncTaxTable *table)
00165 {
00166     timespecFromTime_t (&table->modtime, time(NULL));
00167 }
00168 
00169 static inline void addObj (GncTaxTable *table)
00170 {
00171     struct _book_info *bi;
00172     bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
00173     bi->tables = g_list_insert_sorted (bi->tables, table,
00174                                        (GCompareFunc)gncTaxTableCompare);
00175 }
00176 
00177 static inline void remObj (GncTaxTable *table)
00178 {
00179     struct _book_info *bi;
00180     bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
00181     bi->tables = g_list_remove (bi->tables, table);
00182 }
00183 
00184 static inline void
00185 gncTaxTableAddChild (GncTaxTable *table, GncTaxTable *child)
00186 {
00187     g_return_if_fail(table);
00188     g_return_if_fail(child);
00189     g_return_if_fail(qof_instance_get_destroying(table) == FALSE);
00190 
00191     table->children = g_list_prepend(table->children, child);
00192 }
00193 
00194 static inline void
00195 gncTaxTableRemoveChild (GncTaxTable *table, const GncTaxTable *child)
00196 {
00197     g_return_if_fail(table);
00198     g_return_if_fail(child);
00199 
00200     if (qof_instance_get_destroying(table)) return;
00201 
00202     table->children = g_list_remove(table->children, child);
00203 }
00204 
00205 /* =============================================================== */
00206 
00207 enum
00208 {
00209     PROP_0,
00210     PROP_NAME,
00211     PROP_INVISIBLE,
00212     PROP_REFCOUNT
00213 };
00214 
00215 /* GObject Initialization */
00216 G_DEFINE_TYPE(GncTaxTable, gnc_taxtable, QOF_TYPE_INSTANCE);
00217 
00218 static void
00219 gnc_taxtable_init(GncTaxTable* tt)
00220 {
00221 }
00222 
00223 static void
00224 gnc_taxtable_dispose(GObject *ttp)
00225 {
00226     G_OBJECT_CLASS(gnc_taxtable_parent_class)->dispose(ttp);
00227 }
00228 
00229 static void
00230 gnc_taxtable_finalize(GObject* ttp)
00231 {
00232     G_OBJECT_CLASS(gnc_taxtable_parent_class)->dispose(ttp);
00233 }
00234 
00235 static void
00236 gnc_taxtable_get_property (GObject         *object,
00237                            guint            prop_id,
00238                            GValue          *value,
00239                            GParamSpec      *pspec)
00240 {
00241     GncTaxTable *tt;
00242 
00243     g_return_if_fail(GNC_IS_TAXTABLE(object));
00244 
00245     tt = GNC_TAXTABLE(object);
00246     switch (prop_id)
00247     {
00248     case PROP_NAME:
00249         g_value_set_string(value, tt->name);
00250         break;
00251     case PROP_INVISIBLE:
00252         g_value_set_boolean(value, tt->invisible);
00253         break;
00254     case PROP_REFCOUNT:
00255         g_value_set_uint64(value, tt->refcount);
00256         break;
00257     default:
00258         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
00259         break;
00260     }
00261 }
00262 
00263 static void
00264 gnc_taxtable_set_property (GObject         *object,
00265                            guint            prop_id,
00266                            const GValue          *value,
00267                            GParamSpec      *pspec)
00268 {
00269     GncTaxTable *tt;
00270 
00271     g_return_if_fail(GNC_IS_TAXTABLE(object));
00272 
00273     tt = GNC_TAXTABLE(object);
00274     switch (prop_id)
00275     {
00276     case PROP_NAME:
00277         gncTaxTableSetName(tt, g_value_get_string(value));
00278         break;
00279     case PROP_INVISIBLE:
00280         if (g_value_get_boolean(value))
00281         {
00282             gncTaxTableMakeInvisible(tt);
00283         }
00284         break;
00285     case PROP_REFCOUNT:
00286         gncTaxTableSetRefcount(tt, g_value_get_uint64(value));
00287         break;
00288     default:
00289         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
00290         break;
00291     }
00292 }
00293 
00295 static gchar*
00296 impl_get_display_name(const QofInstance* inst)
00297 {
00298     GncTaxTable* tt;
00299 
00300     g_return_val_if_fail(inst != NULL, FALSE);
00301     g_return_val_if_fail(GNC_IS_TAXTABLE(inst), FALSE);
00302 
00303     tt = GNC_TAXTABLE(inst);
00304     return g_strdup_printf("Tax table %s", tt->name);
00305 }
00306 
00308 static gboolean
00309 impl_refers_to_object(const QofInstance* inst, const QofInstance* ref)
00310 {
00311     GncTaxTable* tt;
00312 
00313     g_return_val_if_fail(inst != NULL, FALSE);
00314     g_return_val_if_fail(GNC_IS_TAXTABLE(inst), FALSE);
00315 
00316     tt = GNC_TAXTABLE(inst);
00317 
00318     if (GNC_IS_ACCOUNT(ref))
00319     {
00320         GList* node;
00321 
00322         for (node = tt->entries; node != NULL; node = node->next)
00323         {
00324             GncTaxTableEntry* tte = node->data;
00325 
00326             if (tte->account == GNC_ACCOUNT(ref))
00327             {
00328                 return TRUE;
00329             }
00330         }
00331     }
00332 
00333     return FALSE;
00334 }
00335 
00342 static GList*
00343 impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
00344 {
00345     if (!GNC_IS_ACCOUNT(ref))
00346     {
00347         return NULL;
00348     }
00349 
00350     return qof_instance_get_referring_object_list_from_collection(qof_instance_get_collection(inst), ref);
00351 }
00352 
00353 static void
00354 gnc_taxtable_class_init (GncTaxTableClass *klass)
00355 {
00356     GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
00357     QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
00358 
00359     gobject_class->dispose = gnc_taxtable_dispose;
00360     gobject_class->finalize = gnc_taxtable_finalize;
00361     gobject_class->set_property = gnc_taxtable_set_property;
00362     gobject_class->get_property = gnc_taxtable_get_property;
00363 
00364     qof_class->get_display_name = impl_get_display_name;
00365     qof_class->refers_to_object = impl_refers_to_object;
00366     qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
00367 
00368     g_object_class_install_property
00369     (gobject_class,
00370      PROP_NAME,
00371      g_param_spec_string ("name",
00372                           "TaxTable Name",
00373                           "The accountName is an arbitrary string "
00374                           "assigned by the user.  It is intended to "
00375                           "a short, 10 to 30 character long string "
00376                           "that is displayed by the GUI as the "
00377                           "tax table mnemonic.",
00378                           NULL,
00379                           G_PARAM_READWRITE));
00380 
00381     g_object_class_install_property
00382     (gobject_class,
00383      PROP_INVISIBLE,
00384      g_param_spec_boolean ("invisible",
00385                            "Invisible",
00386                            "TRUE if the tax table is invisible.  FALSE if visible.",
00387                            FALSE,
00388                            G_PARAM_READWRITE));
00389 
00390     g_object_class_install_property
00391     (gobject_class,
00392      PROP_REFCOUNT,
00393      g_param_spec_uint64("ref-count",
00394                          "Reference count",
00395                          "The ref-count property contains number of times this tax table "
00396                          "is referenced.",
00397                          0,           /* min */
00398                          G_MAXUINT64, /* max */
00399                          0,           /* default */
00400                          G_PARAM_READWRITE));
00401 }
00402 
00403 /* Create/Destroy Functions */
00404 GncTaxTable *
00405 gncTaxTableCreate (QofBook *book)
00406 {
00407     GncTaxTable *table;
00408     if (!book) return NULL;
00409 
00410     table = g_object_new (GNC_TYPE_TAXTABLE, NULL);
00411     qof_instance_init_data (&table->inst, _GNC_MOD_NAME, book);
00412     table->name = CACHE_INSERT ("");
00413     addObj (table);
00414     qof_event_gen (&table->inst, QOF_EVENT_CREATE, NULL);
00415     return table;
00416 }
00417 
00418 void
00419 gncTaxTableDestroy (GncTaxTable *table)
00420 {
00421     if (!table) return;
00422     qof_instance_set_destroying(table, TRUE);
00423     qof_instance_set_dirty (&table->inst);
00424     gncTaxTableCommitEdit (table);
00425 }
00426 
00427 static void
00428 gncTaxTableFree (GncTaxTable *table)
00429 {
00430     GList *list;
00431     GncTaxTable *child;
00432 
00433     if (!table) return;
00434 
00435     qof_event_gen (&table->inst, QOF_EVENT_DESTROY, NULL);
00436     CACHE_REMOVE (table->name);
00437     remObj (table);
00438 
00439     /* destroy the list of entries */
00440     for (list = table->entries; list; list = list->next)
00441         gncTaxTableEntryDestroy (list->data);
00442     g_list_free (table->entries);
00443 
00444     if (!qof_instance_get_destroying(table))
00445         PERR("free a taxtable without do_free set!");
00446 
00447     /* disconnect from parent */
00448     if (table->parent)
00449         gncTaxTableRemoveChild(table->parent, table);
00450 
00451     /* disconnect from the children */
00452     for (list = table->children; list; list = list->next)
00453     {
00454         child = list->data;
00455         gncTaxTableSetParent(child, NULL);
00456     }
00457     g_list_free(table->children);
00458 
00459     /* qof_instance_release (&table->inst); */
00460     g_object_unref (table);
00461 }
00462 
00463 /* =============================================================== */
00464 
00465 GncTaxTableEntry * gncTaxTableEntryCreate (void)
00466 {
00467     GncTaxTableEntry *entry;
00468     entry = g_new0 (GncTaxTableEntry, 1);
00469     entry->amount = gnc_numeric_zero ();
00470     return entry;
00471 }
00472 
00473 void gncTaxTableEntryDestroy (GncTaxTableEntry *entry)
00474 {
00475     if (!entry) return;
00476     g_free (entry);
00477 }
00478 
00479 /* =============================================================== */
00480 /* Set Functions */
00481 
00482 void gncTaxTableSetName (GncTaxTable *table, const char *name)
00483 {
00484     if (!table || !name) return;
00485     SET_STR (table, table->name, name);
00486     mark_table (table);
00487     maybe_resort_list (table);
00488     gncTaxTableCommitEdit (table);
00489 }
00490 
00491 void gncTaxTableSetParent (GncTaxTable *table, GncTaxTable *parent)
00492 {
00493     if (!table) return;
00494     gncTaxTableBeginEdit (table);
00495     if (table->parent)
00496         gncTaxTableRemoveChild(table->parent, table);
00497     table->parent = parent;
00498     if (parent)
00499         gncTaxTableAddChild(parent, table);
00500     table->refcount = 0;
00501     gncTaxTableMakeInvisible (table);
00502     gncTaxTableCommitEdit (table);
00503 }
00504 
00505 void gncTaxTableSetChild (GncTaxTable *table, GncTaxTable *child)
00506 {
00507     if (!table) return;
00508     gncTaxTableBeginEdit (table);
00509     table->child = child;
00510     gncTaxTableCommitEdit (table);
00511 }
00512 
00513 void gncTaxTableIncRef (GncTaxTable *table)
00514 {
00515     if (!table) return;
00516     if (table->parent || table->invisible) return;        /* children dont need refcounts */
00517     gncTaxTableBeginEdit (table);
00518     table->refcount++;
00519     gncTaxTableCommitEdit (table);
00520 }
00521 
00522 void gncTaxTableDecRef (GncTaxTable *table)
00523 {
00524     if (!table) return;
00525     if (table->parent || table->invisible) return;        /* children dont need refcounts */
00526     gncTaxTableBeginEdit (table);
00527     table->refcount--;
00528     g_return_if_fail (table->refcount >= 0);
00529     gncTaxTableCommitEdit (table);
00530 }
00531 
00532 void gncTaxTableSetRefcount (GncTaxTable *table, gint64 refcount)
00533 {
00534     if (!table) return;
00535     table->refcount = refcount;
00536 }
00537 
00538 void gncTaxTableMakeInvisible (GncTaxTable *table)
00539 {
00540     struct _book_info *bi;
00541     if (!table) return;
00542     gncTaxTableBeginEdit (table);
00543     table->invisible = TRUE;
00544     bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
00545     bi->tables = g_list_remove (bi->tables, table);
00546     gncTaxTableCommitEdit (table);
00547 }
00548 
00549 void gncTaxTableEntrySetAccount (GncTaxTableEntry *entry, Account *account)
00550 {
00551     if (!entry || !account) return;
00552     if (entry->account == account) return;
00553     entry->account = account;
00554     if (entry->table)
00555     {
00556         mark_table (entry->table);
00557         mod_table (entry->table);
00558     }
00559 }
00560 
00561 void gncTaxTableEntrySetType (GncTaxTableEntry *entry, GncAmountType type)
00562 {
00563     if (!entry) return;
00564     if (entry->type == type) return;
00565     entry->type = type;
00566     if (entry->table)
00567     {
00568         mark_table (entry->table);
00569         mod_table (entry->table);
00570     }
00571 }
00572 
00573 void gncTaxTableEntrySetAmount (GncTaxTableEntry *entry, gnc_numeric amount)
00574 {
00575     if (!entry) return;
00576     if (gnc_numeric_eq (entry->amount, amount)) return;
00577     entry->amount = amount;
00578     if (entry->table)
00579     {
00580         mark_table (entry->table);
00581         mod_table (entry->table);
00582     }
00583 }
00584 
00585 void gncTaxTableAddEntry (GncTaxTable *table, GncTaxTableEntry *entry)
00586 {
00587     if (!table || !entry) return;
00588     if (entry->table == table) return; /* already mine */
00589 
00590     gncTaxTableBeginEdit (table);
00591     if (entry->table)
00592         gncTaxTableRemoveEntry (entry->table, entry);
00593 
00594     entry->table = table;
00595     table->entries = g_list_insert_sorted (table->entries, entry,
00596                                            (GCompareFunc)gncTaxTableEntryCompare);
00597     mark_table (table);
00598     mod_table (table);
00599     gncTaxTableCommitEdit (table);
00600 }
00601 
00602 void gncTaxTableRemoveEntry (GncTaxTable *table, GncTaxTableEntry *entry)
00603 {
00604     if (!table || !entry) return;
00605     gncTaxTableBeginEdit (table);
00606     entry->table = NULL;
00607     table->entries = g_list_remove (table->entries, entry);
00608     mark_table (table);
00609     mod_table (table);
00610     gncTaxTableCommitEdit (table);
00611 }
00612 
00613 void gncTaxTableChanged (GncTaxTable *table)
00614 {
00615     if (!table) return;
00616     gncTaxTableBeginEdit (table);
00617     table->child = NULL;
00618     gncTaxTableCommitEdit (table);
00619 }
00620 
00621 /* =============================================================== */
00622 
00623 void gncTaxTableBeginEdit (GncTaxTable *table)
00624 {
00625     qof_begin_edit(&table->inst);
00626 }
00627 
00628 static void gncTaxTableOnError (QofInstance *inst, QofBackendError errcode)
00629 {
00630     PERR("TaxTable QofBackend Failure: %d", errcode);
00631     gnc_engine_signal_commit_error( errcode );
00632 }
00633 
00634 static void gncTaxTableOnDone (QofInstance *inst) {}
00635 
00636 static void table_free (QofInstance *inst)
00637 {
00638     GncTaxTable *table = (GncTaxTable *) inst;
00639     gncTaxTableFree (table);
00640 }
00641 
00642 void gncTaxTableCommitEdit (GncTaxTable *table)
00643 {
00644     if (!qof_commit_edit (QOF_INSTANCE(table))) return;
00645     qof_commit_edit_part2 (&table->inst, gncTaxTableOnError,
00646                            gncTaxTableOnDone, table_free);
00647 }
00648 
00649 
00650 /* =============================================================== */
00651 /* Get Functions */
00652 
00653 GncTaxTable *gncTaxTableLookupByName (QofBook *book, const char *name)
00654 {
00655     GList *list = gncTaxTableGetTables (book);
00656 
00657     for ( ; list; list = list->next)
00658     {
00659         GncTaxTable *table = list->data;
00660         if (!safe_strcmp (table->name, name))
00661             return list->data;
00662     }
00663     return NULL;
00664 }
00665 
00666 GList * gncTaxTableGetTables (QofBook *book)
00667 {
00668     struct _book_info *bi;
00669     if (!book) return NULL;
00670 
00671     bi = qof_book_get_data (book, _GNC_MOD_NAME);
00672     return bi->tables;
00673 }
00674 
00675 const char *gncTaxTableGetName (const GncTaxTable *table)
00676 {
00677     if (!table) return NULL;
00678     return table->name;
00679 }
00680 
00681 static GncTaxTableEntry *gncTaxTableEntryCopy (const GncTaxTableEntry *entry)
00682 {
00683     GncTaxTableEntry *e;
00684     if (!entry) return NULL;
00685 
00686     e = gncTaxTableEntryCreate ();
00687     gncTaxTableEntrySetAccount (e, entry->account);
00688     gncTaxTableEntrySetType (e, entry->type);
00689     gncTaxTableEntrySetAmount (e, entry->amount);
00690 
00691     return e;
00692 }
00693 
00694 static GncTaxTable *gncTaxTableCopy (const GncTaxTable *table)
00695 {
00696     GncTaxTable *t;
00697     GList *list;
00698 
00699     if (!table) return NULL;
00700     t = gncTaxTableCreate (qof_instance_get_book(table));
00701     gncTaxTableSetName (t, table->name);
00702     for (list = table->entries; list; list = list->next)
00703     {
00704         GncTaxTableEntry *entry, *e;
00705         entry = list->data;
00706         e = gncTaxTableEntryCopy (entry);
00707         gncTaxTableAddEntry (t, e);
00708     }
00709     return t;
00710 }
00711 
00712 GncTaxTable *gncTaxTableReturnChild (GncTaxTable *table, gboolean make_new)
00713 {
00714     GncTaxTable *child = NULL;
00715 
00716     if (!table) return NULL;
00717     if (table->child) return table->child;
00718     if (table->parent || table->invisible) return table;
00719     if (make_new)
00720     {
00721         child = gncTaxTableCopy (table);
00722         gncTaxTableSetChild (table, child);
00723         gncTaxTableSetParent (child, table);
00724     }
00725     return child;
00726 }
00727 
00728 GncTaxTable *gncTaxTableGetParent (const GncTaxTable *table)
00729 {
00730     if (!table) return NULL;
00731     return table->parent;
00732 }
00733 
00734 GncTaxTableEntryList* gncTaxTableGetEntries (const GncTaxTable *table)
00735 {
00736     if (!table) return NULL;
00737     return table->entries;
00738 }
00739 
00740 gint64 gncTaxTableGetRefcount (const GncTaxTable *table)
00741 {
00742     if (!table) return 0;
00743     return table->refcount;
00744 }
00745 
00746 Timespec gncTaxTableLastModified (const GncTaxTable *table)
00747 {
00748     Timespec ts = { 0 , 0 };
00749     if (!table) return ts;
00750     return table->modtime;
00751 }
00752 
00753 gboolean gncTaxTableGetInvisible (const GncTaxTable *table)
00754 {
00755     if (!table) return FALSE;
00756     return table->invisible;
00757 }
00758 
00759 Account * gncTaxTableEntryGetAccount (const GncTaxTableEntry *entry)
00760 {
00761     if (!entry) return NULL;
00762     return entry->account;
00763 }
00764 
00765 GncAmountType gncTaxTableEntryGetType (const GncTaxTableEntry *entry)
00766 {
00767     if (!entry) return 0;
00768     return entry->type;
00769 }
00770 
00771 gnc_numeric gncTaxTableEntryGetAmount (const GncTaxTableEntry *entry)
00772 {
00773     if (!entry) return gnc_numeric_zero();
00774     return entry->amount;
00775 }
00776 
00777 /* This is a semi-private function (meaning that it's not declared in
00778  * the header) used for SQL Backend testing. */
00779 GncTaxTable* gncTaxTableEntryGetTable( const GncTaxTableEntry* entry )
00780 {
00781     if (!entry) return NULL;
00782     return entry->table;
00783 }
00784 
00785 int gncTaxTableEntryCompare (const GncTaxTableEntry *a, const GncTaxTableEntry *b)
00786 {
00787     char *name_a, *name_b;
00788     int retval;
00789 
00790     if (!a && !b) return 0;
00791     if (!a) return -1;
00792     if (!b) return 1;
00793 
00794     name_a = gnc_account_get_full_name (a->account);
00795     name_b = gnc_account_get_full_name (b->account);
00796     retval = safe_strcmp(name_a, name_b);
00797     g_free(name_a);
00798     g_free(name_b);
00799 
00800     if (retval)
00801         return retval;
00802 
00803     return gnc_numeric_compare (a->amount, b->amount);
00804 }
00805 
00806 int gncTaxTableCompare (const GncTaxTable *a, const GncTaxTable *b)
00807 {
00808     if (!a && !b) return 0;
00809     if (!a) return -1;
00810     if (!b) return 1;
00811     return safe_strcmp (a->name, b->name);
00812 }
00813 
00814 gboolean gncTaxTableEntryEqual(const GncTaxTableEntry *a, const GncTaxTableEntry *b)
00815 {
00816     if (a == NULL && b == NULL) return TRUE;
00817     if (a == NULL || b == NULL) return FALSE;
00818 
00819     if (!xaccAccountEqual(a->account, b->account, TRUE))
00820     {
00821         PWARN("accounts differ");
00822         return FALSE;
00823     }
00824 
00825     if (a->type != b->type)
00826     {
00827         PWARN("types differ");
00828         return FALSE;
00829     }
00830 
00831     if (!gnc_numeric_equal(a->amount, b->amount))
00832     {
00833         PWARN("amounts differ");
00834         return FALSE;
00835     }
00836 
00837     return TRUE;
00838 }
00839 
00840 gboolean gncTaxTableEqual(const GncTaxTable *a, const GncTaxTable *b)
00841 {
00842     if (a == NULL && b == NULL) return TRUE;
00843     if (a == NULL || b == NULL) return FALSE;
00844 
00845     g_return_val_if_fail(GNC_IS_TAXTABLE(a), FALSE);
00846     g_return_val_if_fail(GNC_IS_TAXTABLE(b), FALSE);
00847 
00848     if (safe_strcmp(a->name, b->name) != 0)
00849     {
00850         PWARN("Names differ: %s vs %s", a->name, b->name);
00851         return FALSE;
00852     }
00853 
00854     if (a->invisible != b->invisible)
00855     {
00856         PWARN("invisible flags differ");
00857         return FALSE;
00858     }
00859 
00860     if ((a->entries != NULL) != (b->entries != NULL))
00861     {
00862         PWARN("only one has entries");
00863         return FALSE;
00864     }
00865 
00866     if (a->entries != NULL && b->entries != NULL)
00867     {
00868         GncTaxTableEntryList* a_node;
00869         GncTaxTableEntryList* b_node;
00870 
00871         for (a_node = a->entries, b_node = b->entries;
00872                 a_node != NULL && b_node != NULL;
00873                 a_node = a_node->next, b_node = b_node->next)
00874         {
00875             if (!gncTaxTableEntryEqual((GncTaxTableEntry*)a_node->data,
00876                                        (GncTaxTableEntry*)b_node->data))
00877             {
00878                 PWARN("entries differ");
00879                 return FALSE;
00880             }
00881         }
00882 
00883         if (a_node != NULL || b_node != NULL)
00884         {
00885             PWARN("Unequal number of entries");
00886             return FALSE;
00887         }
00888     }
00889 
00890 #if 0
00891     /* See src/doc/business.txt for an explanation of the following */
00892     /* Code that handles this is *identical* to that in gncBillTerm */
00893     gint64          refcount;
00894     GncTaxTable *   parent;       /* if non-null, we are an immutable child */
00895     GncTaxTable *   child;        /* if non-null, we have not changed */
00896     GList *         children;     /* list of children for disconnection */
00897 #endif
00898 
00899     return TRUE;
00900 }
00901 
00902 /*
00903  * This will add value to the account-value for acc, creating a new
00904  * list object if necessary
00905  */
00906 GList *gncAccountValueAdd (GList *list, Account *acc, gnc_numeric value)
00907 {
00908     GList *li;
00909     GncAccountValue *res = NULL;
00910 
00911     g_return_val_if_fail (acc, list);
00912     g_return_val_if_fail (gnc_numeric_check (value) == GNC_ERROR_OK, list);
00913 
00914     /* Try to find the account in the list */
00915     for (li = list; li; li = li->next)
00916     {
00917         res = li->data;
00918         if (res->account == acc)
00919         {
00920             res->value = gnc_numeric_add (res->value, value, GNC_DENOM_AUTO,
00921                                           GNC_HOW_DENOM_LCD);
00922             return list;
00923         }
00924     }
00925     /* Nope, didn't find it. */
00926 
00927     res = g_new0 (GncAccountValue, 1);
00928     res->account = acc;
00929     res->value = value;
00930     return g_list_prepend (list, res);
00931 }
00932 
00933 /* Merge l2 into l1.  l2 is not touched. */
00934 GList *gncAccountValueAddList (GList *l1, GList *l2)
00935 {
00936     GList *li;
00937 
00938     for (li = l2; li; li = li->next )
00939     {
00940         GncAccountValue *val = li->data;
00941         l1 = gncAccountValueAdd (l1, val->account, val->value);
00942     }
00943 
00944     return l1;
00945 }
00946 
00947 /* return the total for this list */
00948 gnc_numeric gncAccountValueTotal (GList *list)
00949 {
00950     gnc_numeric total = gnc_numeric_zero ();
00951 
00952     for ( ; list ; list = list->next)
00953     {
00954         GncAccountValue *val = list->data;
00955         total = gnc_numeric_add (total, val->value, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
00956     }
00957     return total;
00958 }
00959 
00960 /* Destroy a list of accountvalues */
00961 void gncAccountValueDestroy (GList *list)
00962 {
00963     GList *node;
00964     for ( node = list; node ; node = node->next)
00965         g_free (node->data);
00966 
00967     g_list_free (list);
00968 }
00969 
00970 /* Package-Private functions */
00971 
00972 static void _gncTaxTableCreate (QofBook *book)
00973 {
00974     struct _book_info *bi;
00975 
00976     if (!book) return;
00977 
00978     bi = g_new0 (struct _book_info, 1);
00979     qof_book_set_data (book, _GNC_MOD_NAME, bi);
00980 }
00981 
00982 static void _gncTaxTableDestroy (QofBook *book)
00983 {
00984     struct _book_info *bi;
00985 
00986     if (!book) return;
00987 
00988     bi = qof_book_get_data (book, _GNC_MOD_NAME);
00989 
00990     g_list_free (bi->tables);
00991     g_free (bi);
00992 }
00993 
00994 static QofObject gncTaxTableDesc =
00995 {
00996     DI(.interface_version = ) QOF_OBJECT_VERSION,
00997     DI(.e_type            = ) _GNC_MOD_NAME,
00998     DI(.type_label        = ) "Tax Table",
00999     DI(.create            = ) (gpointer)gncTaxTableCreate,
01000     DI(.book_begin        = ) _gncTaxTableCreate,
01001     DI(.book_end          = ) _gncTaxTableDestroy,
01002     DI(.is_dirty          = ) qof_collection_is_dirty,
01003     DI(.mark_clean        = ) qof_collection_mark_clean,
01004     DI(.foreach           = ) qof_collection_foreach,
01005     DI(.printable         = ) NULL,
01006     DI(.version_cmp       = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
01007 };
01008 
01009 gboolean gncTaxTableRegister (void)
01010 {
01011     static QofParam params[] =
01012     {
01013         { GNC_TT_NAME,          QOF_TYPE_STRING,        (QofAccessFunc)gncTaxTableGetName,              (QofSetterFunc)gncTaxTableSetName },
01014         { GNC_TT_REFCOUNT,      QOF_TYPE_INT64,         (QofAccessFunc)gncTaxTableGetRefcount,  (QofSetterFunc)gncTaxTableSetRefcount },
01015         { QOF_PARAM_BOOK,       QOF_ID_BOOK,            (QofAccessFunc)qof_instance_get_book,   NULL },
01016         { QOF_PARAM_GUID,       QOF_TYPE_GUID,          (QofAccessFunc)qof_instance_get_guid,   NULL },
01017         { NULL },
01018     };
01019 
01020     qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncTaxTableCompare, params);
01021 
01022     return qof_object_register (&gncTaxTableDesc);
01023 }
01024 
01025 /* need a QOF tax table entry object */
01026 //gncTaxTableEntrySetType_q int32
01027 //gint gncTaxTableEntryGetType_q (GncTaxTableEntry *entry);
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines