LCOV - code coverage report
Current view: top level - libgnucash/engine - gncTaxTable.c (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 73.8 % 469 346
Test Date: 2026-11-02 18:19:43 Functions: 82.4 % 74 61
Legend: Lines:     hit not hit

            Line data    Source code
       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              : 
      37              : struct _gncTaxTable
      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              : 
      53              : struct _gncTaxTableClass
      54              : {
      55              :     QofInstanceClass parent_class;
      56              : };
      57              : 
      58              : struct _gncTaxTableEntry
      59              : {
      60              :     GncTaxTable *   table;
      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           41 : gncAmountTypeToString (GncAmountType type)
      80              : {
      81           41 :     switch (type)
      82              :     {
      83           20 :         GNC_RETURN_ENUM_AS_STRING(GNC_AMT_TYPE_VALUE, "VALUE");
      84           21 :         GNC_RETURN_ENUM_AS_STRING(GNC_AMT_TYPE_PERCENT, "PERCENT");
      85            0 :     default:
      86            0 :         g_warning ("asked to translate unknown amount type %d.\n", type);
      87            0 :         break;
      88              :     }
      89            0 :     return(NULL);
      90              : }
      91              : 
      92              : const char *
      93            3 : gncTaxIncludedTypeToString (GncTaxIncluded type)
      94              : {
      95            3 :     switch (type)
      96              :     {
      97            0 :         GNC_RETURN_ENUM_AS_STRING(GNC_TAXINCLUDED_YES, "YES");
      98            0 :         GNC_RETURN_ENUM_AS_STRING(GNC_TAXINCLUDED_NO, "NO");
      99            3 :         GNC_RETURN_ENUM_AS_STRING(GNC_TAXINCLUDED_USEGLOBAL, "USEGLOBAL");
     100            0 :     default:
     101            0 :         g_warning ("asked to translate unknown taxincluded type %d.\n", type);
     102            0 :         break;
     103              :     }
     104            0 :     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            3 : gncAmountStringToType (const char *str, GncAmountType *type)
     111              : {
     112            3 :     GNC_RETURN_ON_MATCH ("VALUE", GNC_AMT_TYPE_VALUE);
     113            3 :     GNC_RETURN_ON_MATCH ("PERCENT", GNC_AMT_TYPE_PERCENT);
     114            0 :     g_warning ("asked to translate unknown amount type string %s.\n",
     115              :                str ? str : "(null)");
     116              : 
     117            0 :     return(FALSE);
     118              : }
     119              : 
     120              : gboolean
     121            5 : gncTaxIncludedStringToType (const char *str, GncTaxIncluded *type)
     122              : {
     123            5 :     GNC_RETURN_ON_MATCH ("YES", GNC_TAXINCLUDED_YES);
     124            5 :     GNC_RETURN_ON_MATCH ("NO", GNC_TAXINCLUDED_NO);
     125            5 :     GNC_RETURN_ON_MATCH ("USEGLOBAL", GNC_TAXINCLUDED_USEGLOBAL);
     126            0 :     g_warning ("asked to translate unknown taxincluded type string %s.\n",
     127              :                str ? str : "(null)");
     128              : 
     129            0 :     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              : 
     144              : static inline void
     145          192 : mark_table (GncTaxTable *table)
     146              : {
     147          192 :     qof_instance_set_dirty(&table->inst);
     148          192 :     qof_event_gen (&table->inst, QOF_EVENT_MODIFY, NULL);
     149          192 : }
     150              : 
     151              : static inline void
     152           29 : maybe_resort_list (GncTaxTable *table)
     153              : {
     154              :     struct _book_info *bi;
     155              : 
     156           29 :     if (table->parent || table->invisible) return;
     157           29 :     bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
     158           29 :     bi->tables = g_list_sort (bi->tables, (GCompareFunc)gncTaxTableCompare);
     159              : }
     160              : 
     161              : static inline void
     162           38 : mod_table (GncTaxTable *table)
     163              : {
     164           38 :     table->modtime = gnc_time (NULL);
     165           38 : }
     166              : 
     167           29 : static inline void addObj (GncTaxTable *table)
     168              : {
     169              :     struct _book_info *bi;
     170           29 :     bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
     171           29 :     bi->tables = g_list_insert_sorted (bi->tables, table,
     172              :                                        (GCompareFunc)gncTaxTableCompare);
     173           29 : }
     174              : 
     175            7 : static inline void remObj (GncTaxTable *table)
     176              : {
     177              :     struct _book_info *bi;
     178            7 :     bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
     179            7 :     bi->tables = g_list_remove (bi->tables, table);
     180            7 : }
     181              : 
     182              : static inline void
     183            5 : gncTaxTableAddChild (GncTaxTable *table, GncTaxTable *child)
     184              : {
     185            5 :     g_return_if_fail(table);
     186            5 :     g_return_if_fail(child);
     187            5 :     g_return_if_fail(qof_instance_get_destroying(table) == FALSE);
     188              : 
     189            5 :     table->children = g_list_prepend(table->children, child);
     190              : }
     191              : 
     192              : static inline void
     193            0 : gncTaxTableRemoveChild (GncTaxTable *table, const GncTaxTable *child)
     194              : {
     195            0 :     g_return_if_fail(table);
     196            0 :     g_return_if_fail(child);
     197              : 
     198            0 :     if (qof_instance_get_destroying(table)) return;
     199              : 
     200            0 :     table->children = g_list_remove(table->children, child);
     201              : }
     202              : 
     203              : /* =============================================================== */
     204              : 
     205              : enum
     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 */
     215           96 : G_DEFINE_TYPE(GncTaxTable, gnc_taxtable, QOF_TYPE_INSTANCE)
     216              : 
     217              : static void
     218           29 : gnc_taxtable_init(GncTaxTable* tt)
     219              : {
     220           29 : }
     221              : 
     222              : static void
     223            7 : gnc_taxtable_dispose(GObject *ttp)
     224              : {
     225            7 :     G_OBJECT_CLASS(gnc_taxtable_parent_class)->dispose(ttp);
     226            7 : }
     227              : 
     228              : static void
     229            7 : gnc_taxtable_finalize(GObject* ttp)
     230              : {
     231            7 :     G_OBJECT_CLASS(gnc_taxtable_parent_class)->finalize(ttp);
     232            7 : }
     233              : 
     234              : static void
     235            6 : gnc_taxtable_get_property (GObject         *object,
     236              :                            guint            prop_id,
     237              :                            GValue          *value,
     238              :                            GParamSpec      *pspec)
     239              : {
     240              :     GncTaxTable *tt;
     241              : 
     242            6 :     g_return_if_fail(GNC_IS_TAXTABLE(object));
     243              : 
     244            6 :     tt = GNC_TAXTABLE(object);
     245            6 :     switch (prop_id)
     246              :     {
     247            2 :     case PROP_NAME:
     248            2 :         g_value_set_string(value, tt->name);
     249            2 :         break;
     250            2 :     case PROP_INVISIBLE:
     251            2 :         g_value_set_boolean(value, tt->invisible);
     252            2 :         break;
     253            2 :     case PROP_REFCOUNT:
     254            2 :         g_value_set_uint64(value, tt->refcount);
     255            2 :         break;
     256            0 :     default:
     257            0 :         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
     258            0 :         break;
     259              :     }
     260              : }
     261              : 
     262              : static void
     263            6 : gnc_taxtable_set_property (GObject         *object,
     264              :                            guint            prop_id,
     265              :                            const GValue          *value,
     266              :                            GParamSpec      *pspec)
     267              : {
     268              :     GncTaxTable *tt;
     269              : 
     270            6 :     g_return_if_fail(GNC_IS_TAXTABLE(object));
     271              : 
     272            6 :     tt = GNC_TAXTABLE(object);
     273            6 :     g_assert (qof_instance_get_editlevel(tt));
     274              : 
     275            6 :     switch (prop_id)
     276              :     {
     277            2 :     case PROP_NAME:
     278            2 :         gncTaxTableSetName(tt, g_value_get_string(value));
     279            2 :         break;
     280            2 :     case PROP_INVISIBLE:
     281            2 :         if (g_value_get_boolean(value))
     282              :         {
     283            0 :             gncTaxTableMakeInvisible(tt);
     284              :         }
     285            2 :         break;
     286            2 :     case PROP_REFCOUNT:
     287            2 :         gncTaxTableSetRefcount(tt, g_value_get_uint64(value));
     288            2 :         break;
     289            0 :     default:
     290            0 :         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
     291            0 :         break;
     292              :     }
     293              : }
     294              : 
     295              : /** Return displayable name */
     296              : static gchar*
     297            0 : impl_get_display_name(const QofInstance* inst)
     298              : {
     299              :     GncTaxTable* tt;
     300              : 
     301            0 :     g_return_val_if_fail(inst != NULL, FALSE);
     302            0 :     g_return_val_if_fail(GNC_IS_TAXTABLE(inst), FALSE);
     303              : 
     304            0 :     tt = GNC_TAXTABLE(inst);
     305            0 :     return g_strdup_printf("Tax table %s", tt->name);
     306              : }
     307              : 
     308              : /** Does this object refer to a specific object */
     309              : static gboolean
     310            0 : impl_refers_to_object(const QofInstance* inst, const QofInstance* ref)
     311              : {
     312              :     GncTaxTable* tt;
     313              : 
     314            0 :     g_return_val_if_fail(inst != NULL, FALSE);
     315            0 :     g_return_val_if_fail(GNC_IS_TAXTABLE(inst), FALSE);
     316              : 
     317            0 :     tt = GNC_TAXTABLE(inst);
     318              : 
     319            0 :     if (GNC_IS_ACCOUNT(ref))
     320              :     {
     321              :         GList* node;
     322              : 
     323            0 :         for (node = tt->entries; node != NULL; node = node->next)
     324              :         {
     325            0 :             GncTaxTableEntry* tte = node->data;
     326              : 
     327            0 :             if (tte->account == GNC_ACCOUNT(ref))
     328              :             {
     329            0 :                 return TRUE;
     330              :             }
     331              :         }
     332              :     }
     333              : 
     334            0 :     return FALSE;
     335              : }
     336              : 
     337              : /** Returns a list of my type of object which refers to an object.  For example, when called as
     338              :         qof_instance_get_typed_referring_object_list(taxtable, account);
     339              :     it will return the list of taxtables which refer to a specific account.  The result should be the
     340              :     same regardless of which taxtable object is used.  The list must be freed by the caller but the
     341              :     objects on the list must not.
     342              :  */
     343              : static GList*
     344            0 : impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
     345              : {
     346            0 :     if (!GNC_IS_ACCOUNT(ref))
     347              :     {
     348            0 :         return NULL;
     349              :     }
     350              : 
     351            0 :     return qof_instance_get_referring_object_list_from_collection(qof_instance_get_collection(inst), ref);
     352              : }
     353              : 
     354              : static void
     355            7 : gnc_taxtable_class_init (GncTaxTableClass *klass)
     356              : {
     357            7 :     GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     358            7 :     QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
     359              : 
     360            7 :     gobject_class->dispose = gnc_taxtable_dispose;
     361            7 :     gobject_class->finalize = gnc_taxtable_finalize;
     362            7 :     gobject_class->set_property = gnc_taxtable_set_property;
     363            7 :     gobject_class->get_property = gnc_taxtable_get_property;
     364              : 
     365            7 :     qof_class->get_display_name = impl_get_display_name;
     366            7 :     qof_class->refers_to_object = impl_refers_to_object;
     367            7 :     qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
     368              : 
     369            7 :     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            7 :     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            7 :     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            7 : }
     403              : 
     404              : /* Create/Destroy Functions */
     405              : GncTaxTable *
     406           29 : gncTaxTableCreate (QofBook *book)
     407              : {
     408              :     GncTaxTable *table;
     409           29 :     if (!book) return NULL;
     410              : 
     411           29 :     table = g_object_new (GNC_TYPE_TAXTABLE, NULL);
     412           29 :     qof_instance_init_data (&table->inst, _GNC_MOD_NAME, book);
     413           29 :     table->name = CACHE_INSERT ("");
     414           29 :     addObj (table);
     415           29 :     qof_event_gen (&table->inst, QOF_EVENT_CREATE, NULL);
     416           29 :     return table;
     417              : }
     418              : 
     419              : void
     420            7 : gncTaxTableDestroy (GncTaxTable *table)
     421              : {
     422            7 :     if (!table) return;
     423            7 :     qof_instance_set_destroying(table, TRUE);
     424            7 :     qof_instance_set_dirty (&table->inst);
     425            7 :     gncTaxTableCommitEdit (table);
     426              : }
     427              : 
     428              : static void
     429            7 : gncTaxTableFree (GncTaxTable *table)
     430              : {
     431              :     GList *list;
     432              :     GncTaxTable *child;
     433              : 
     434            7 :     if (!table) return;
     435              : 
     436            7 :     qof_event_gen (&table->inst, QOF_EVENT_DESTROY, NULL);
     437            7 :     CACHE_REMOVE (table->name);
     438            7 :     remObj (table);
     439              : 
     440              :     /* destroy the list of entries */
     441           16 :     for (list = table->entries; list; list = list->next)
     442            9 :         gncTaxTableEntryDestroy (list->data);
     443            7 :     g_list_free (table->entries);
     444              : 
     445            7 :     if (!qof_instance_get_destroying(table))
     446            0 :         PERR("free a taxtable without do_free set!");
     447              : 
     448              :     /* disconnect from parent */
     449            7 :     if (table->parent)
     450            0 :         gncTaxTableRemoveChild(table->parent, table);
     451              : 
     452              :     /* disconnect from the children */
     453            7 :     for (list = table->children; list; list = list->next)
     454              :     {
     455            0 :         child = list->data;
     456            0 :         gncTaxTableSetParent(child, NULL);
     457              :     }
     458            7 :     g_list_free(table->children);
     459              : 
     460              :     /* qof_instance_release (&table->inst); */
     461            7 :     g_object_unref (table);
     462              : }
     463              : 
     464              : /* =============================================================== */
     465              : 
     466           31 : GncTaxTableEntry * gncTaxTableEntryCreate (void)
     467              : {
     468              :     GncTaxTableEntry *entry;
     469           31 :     entry = g_new0 (GncTaxTableEntry, 1);
     470           31 :     entry->amount = gnc_numeric_zero ();
     471           31 :     return entry;
     472              : }
     473              : 
     474            9 : void gncTaxTableEntryDestroy (GncTaxTableEntry *entry)
     475              : {
     476            9 :     if (!entry) return;
     477            9 :     g_free (entry);
     478              : }
     479              : 
     480              : /* =============================================================== */
     481              : /* Set Functions */
     482              : 
     483           29 : void gncTaxTableSetName (GncTaxTable *table, const char *name)
     484              : {
     485           29 :     if (!table || !name) return;
     486           29 :     SET_STR (table, table->name, name);
     487           29 :     mark_table (table);
     488           29 :     maybe_resort_list (table);
     489           29 :     gncTaxTableCommitEdit (table);
     490              : }
     491              : 
     492            5 : void gncTaxTableSetParent (GncTaxTable *table, GncTaxTable *parent)
     493              : {
     494            5 :     if (!table) return;
     495            5 :     gncTaxTableBeginEdit (table);
     496            5 :     if (table->parent)
     497            0 :         gncTaxTableRemoveChild(table->parent, table);
     498            5 :     table->parent = parent;
     499            5 :     if (parent)
     500            5 :         gncTaxTableAddChild(parent, table);
     501            5 :     table->refcount = 0;
     502            5 :     gncTaxTableMakeInvisible (table);
     503            5 :     mark_table (table);
     504            5 :     gncTaxTableCommitEdit (table);
     505              : }
     506              : 
     507            5 : void gncTaxTableSetChild (GncTaxTable *table, GncTaxTable *child)
     508              : {
     509            5 :     if (!table) return;
     510            5 :     gncTaxTableBeginEdit (table);
     511            5 :     table->child = child;
     512            5 :     mark_table (table);
     513            5 :     gncTaxTableCommitEdit (table);
     514              : }
     515              : 
     516          106 : void gncTaxTableIncRef (GncTaxTable *table)
     517              : {
     518          106 :     if (!table) return;
     519          106 :     if (table->parent || table->invisible) return;        /* children dont need refcounts */
     520           66 :     gncTaxTableBeginEdit (table);
     521           66 :     table->refcount++;
     522           66 :     mark_table (table);
     523           66 :     gncTaxTableCommitEdit (table);
     524              : }
     525              : 
     526           46 : void gncTaxTableDecRef (GncTaxTable *table)
     527              : {
     528           46 :     if (!table) return;
     529           46 :     if (table->parent || table->invisible) return;        /* children dont need refcounts */
     530           46 :     g_return_if_fail (table->refcount > 0);
     531           46 :     gncTaxTableBeginEdit (table);
     532           46 :     table->refcount--;
     533           46 :     mark_table (table);
     534           46 :     gncTaxTableCommitEdit (table);
     535              : }
     536              : 
     537            3 : void gncTaxTableSetRefcount (GncTaxTable *table, gint64 refcount)
     538              : {
     539            3 :     if (!table) return;
     540            3 :     g_return_if_fail (refcount >= 0);
     541            3 :     gncTaxTableBeginEdit (table);
     542            3 :     table->refcount = refcount;
     543            3 :     mark_table (table);
     544            3 :     gncTaxTableCommitEdit (table);
     545              : }
     546              : 
     547            5 : void gncTaxTableMakeInvisible (GncTaxTable *table)
     548              : {
     549              :     struct _book_info *bi;
     550            5 :     if (!table) return;
     551            5 :     gncTaxTableBeginEdit (table);
     552            5 :     table->invisible = TRUE;
     553            5 :     bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME);
     554            5 :     bi->tables = g_list_remove (bi->tables, table);
     555            5 :     gncTaxTableCommitEdit (table);
     556              : }
     557              : 
     558           31 : void gncTaxTableEntrySetAccount (GncTaxTableEntry *entry, Account *account)
     559              : {
     560           31 :     if (!entry || !account) return;
     561           31 :     if (entry->account == account) return;
     562           31 :     entry->account = account;
     563           31 :     if (entry->table)
     564              :     {
     565            0 :         mark_table (entry->table);
     566            0 :         mod_table (entry->table);
     567              :     }
     568              : }
     569              : 
     570           31 : void gncTaxTableEntrySetType (GncTaxTableEntry *entry, GncAmountType type)
     571              : {
     572           31 :     if (!entry) return;
     573           31 :     if (entry->type == type) return;
     574           31 :     entry->type = type;
     575           31 :     if (entry->table)
     576              :     {
     577            0 :         mark_table (entry->table);
     578            0 :         mod_table (entry->table);
     579              :     }
     580              : }
     581              : 
     582           38 : void gncTaxTableEntrySetAmount (GncTaxTableEntry *entry, gnc_numeric amount)
     583              : {
     584           38 :     if (!entry) return;
     585           38 :     if (gnc_numeric_eq (entry->amount, amount)) return;
     586           34 :     entry->amount = amount;
     587           34 :     if (entry->table)
     588              :     {
     589            7 :         mark_table (entry->table);
     590            7 :         mod_table (entry->table);
     591              :     }
     592              : }
     593              : 
     594           31 : void gncTaxTableAddEntry (GncTaxTable *table, GncTaxTableEntry *entry)
     595              : {
     596           31 :     if (!table || !entry) return;
     597           31 :     if (entry->table == table) return; /* already mine */
     598              : 
     599           31 :     gncTaxTableBeginEdit (table);
     600           31 :     if (entry->table)
     601            0 :         gncTaxTableRemoveEntry (entry->table, entry);
     602              : 
     603           31 :     entry->table = table;
     604           31 :     table->entries = g_list_insert_sorted (table->entries, entry,
     605              :                                            (GCompareFunc)gncTaxTableEntryCompare);
     606           31 :     mark_table (table);
     607           31 :     mod_table (table);
     608           31 :     gncTaxTableCommitEdit (table);
     609              : }
     610              : 
     611            0 : void gncTaxTableRemoveEntry (GncTaxTable *table, GncTaxTableEntry *entry)
     612              : {
     613            0 :     if (!table || !entry) return;
     614            0 :     gncTaxTableBeginEdit (table);
     615            0 :     entry->table = NULL;
     616            0 :     table->entries = g_list_remove (table->entries, entry);
     617            0 :     mark_table (table);
     618            0 :     mod_table (table);
     619            0 :     gncTaxTableCommitEdit (table);
     620              : }
     621              : 
     622            0 : void gncTaxTableChanged (GncTaxTable *table)
     623              : {
     624            0 :     if (!table) return;
     625            0 :     gncTaxTableBeginEdit (table);
     626            0 :     table->child = NULL;
     627            0 :     gncTaxTableCommitEdit (table);
     628              : }
     629              : 
     630              : /* =============================================================== */
     631              : 
     632          198 : void gncTaxTableBeginEdit (GncTaxTable *table)
     633              : {
     634          198 :     qof_begin_edit(&table->inst);
     635          198 : }
     636              : 
     637            0 : static void gncTaxTableOnError (QofInstance *inst, QofBackendError errcode)
     638              : {
     639            0 :     PERR("TaxTable QofBackend Failure: %d", errcode);
     640            0 :     gnc_engine_signal_commit_error( errcode );
     641            0 : }
     642              : 
     643          179 : static void gncTaxTableOnDone (QofInstance *inst) {}
     644              : 
     645            7 : static void table_free (QofInstance *inst)
     646              : {
     647            7 :     GncTaxTable *table = (GncTaxTable *) inst;
     648            7 :     gncTaxTableFree (table);
     649            7 : }
     650              : 
     651          198 : void gncTaxTableCommitEdit (GncTaxTable *table)
     652              : {
     653              :     /* GnuCash 2.6.3 and earlier didn't handle taxtable kvp's... */
     654          198 :      if (qof_instance_has_kvp (QOF_INSTANCE (table)))
     655            0 :           gnc_features_set_used (qof_instance_get_book (QOF_INSTANCE (table)),
     656              :                                  GNC_FEATURE_KVP_EXTRA_DATA);
     657              : 
     658          198 :     if (!qof_commit_edit (QOF_INSTANCE(table))) return;
     659          186 :     qof_commit_edit_part2 (&table->inst, gncTaxTableOnError,
     660              :                            gncTaxTableOnDone, table_free);
     661              : }
     662              : 
     663              : 
     664              : /* =============================================================== */
     665              : /* Get Functions */
     666              : 
     667            0 : GncTaxTable *gncTaxTableLookupByName (QofBook *book, const char *name)
     668              : {
     669            0 :     GList *list = gncTaxTableGetTables (book);
     670              : 
     671            0 :     for ( ; list; list = list->next)
     672              :     {
     673            0 :         GncTaxTable *table = list->data;
     674            0 :         if (!g_strcmp0 (table->name, name))
     675            0 :             return list->data;
     676              :     }
     677            0 :     return NULL;
     678              : }
     679              : 
     680              : GncTaxTable*
     681            0 : gncTaxTableGetDefault (QofBook *book, GncOwnerType type)
     682              : {
     683            0 :     GSList *path = NULL;
     684            0 :     const GncGUID *guid = NULL;
     685            0 :     const char *vendor = "Default Vendor TaxTable";
     686            0 :     const char *customer = "Default Customer TaxTable";
     687            0 :     const char *section = "Business";
     688              : 
     689            0 :     g_return_val_if_fail (book != NULL, NULL);
     690            0 :     g_return_val_if_fail (type == GNC_OWNER_CUSTOMER || \
     691              :                           type == GNC_OWNER_VENDOR, NULL);
     692            0 :     path = g_slist_prepend (path, type == GNC_OWNER_CUSTOMER ? (void*)customer : (void*)vendor);
     693            0 :     path = g_slist_prepend (path, (void*)section);
     694              : 
     695            0 :     guid = qof_book_get_guid_option (book, path);
     696            0 :     g_slist_free (path);
     697              : 
     698            0 :     return gncTaxTableLookup (book, guid);
     699              : }
     700              : 
     701            0 : GncTaxTableList * gncTaxTableGetTables (QofBook *book)
     702              : {
     703              :     struct _book_info *bi;
     704            0 :     if (!book) return NULL;
     705              : 
     706            0 :     bi = qof_book_get_data (book, _GNC_MOD_NAME);
     707            0 :     return bi ? bi->tables : NULL;
     708              : }
     709              : 
     710            0 : const char *gncTaxTableGetName (const GncTaxTable *table)
     711              : {
     712            0 :     if (!table) return NULL;
     713            0 :     return table->name;
     714              : }
     715              : 
     716            5 : static GncTaxTableEntry *gncTaxTableEntryCopy (const GncTaxTableEntry *entry)
     717              : {
     718              :     GncTaxTableEntry *e;
     719            5 :     if (!entry) return NULL;
     720              : 
     721            5 :     e = gncTaxTableEntryCreate ();
     722            5 :     gncTaxTableEntrySetAccount (e, entry->account);
     723            5 :     gncTaxTableEntrySetType (e, entry->type);
     724            5 :     gncTaxTableEntrySetAmount (e, entry->amount);
     725              : 
     726            5 :     return e;
     727              : }
     728              : 
     729            5 : static GncTaxTable *gncTaxTableCopy (const GncTaxTable *table)
     730              : {
     731              :     GncTaxTable *t;
     732              :     GList *list;
     733              : 
     734            5 :     if (!table) return NULL;
     735            5 :     t = gncTaxTableCreate (qof_instance_get_book(table));
     736            5 :     gncTaxTableSetName (t, table->name);
     737           10 :     for (list = table->entries; list; list = list->next)
     738              :     {
     739              :         GncTaxTableEntry *entry, *e;
     740            5 :         entry = list->data;
     741            5 :         e = gncTaxTableEntryCopy (entry);
     742              :        /* Clang static analyzer thinks we're leaking e, but we're not.
     743              :         * We're transferring it to table. */
     744            5 :         gncTaxTableAddEntry (t, e);
     745              :     }
     746            5 :     return t;
     747              : }
     748              : 
     749          108 : GncTaxTable *gncTaxTableReturnChild (GncTaxTable *table, gboolean make_new)
     750              : {
     751          108 :     GncTaxTable *child = NULL;
     752              : 
     753          108 :     if (!table) return NULL;
     754           40 :     if (table->child) return table->child;
     755            5 :     if (table->parent || table->invisible) return table;
     756            5 :     if (make_new)
     757              :     {
     758            5 :         child = gncTaxTableCopy (table);
     759            5 :         gncTaxTableSetChild (table, child);
     760            5 :         gncTaxTableSetParent (child, table);
     761              :     }
     762            5 :     return child;
     763              : }
     764              : 
     765           13 : GncTaxTable *gncTaxTableGetParent (const GncTaxTable *table)
     766              : {
     767           13 :     if (!table) return NULL;
     768            5 :     return table->parent;
     769              : }
     770              : 
     771          319 : GncTaxTableEntryList* gncTaxTableGetEntries (const GncTaxTable *table)
     772              : {
     773          319 :     if (!table) return NULL;
     774           63 :     return table->entries;
     775              : }
     776              : 
     777            0 : gint64 gncTaxTableGetRefcount (const GncTaxTable *table)
     778              : {
     779            0 :     if (!table) return 0;
     780            0 :     return table->refcount;
     781              : }
     782              : 
     783          528 : time64 gncTaxTableLastModifiedSecs (const GncTaxTable *table)
     784              : {
     785          528 :     if (!table) return 0;
     786          528 :     return table->modtime;
     787              : }
     788              : 
     789            0 : gboolean gncTaxTableGetInvisible (const GncTaxTable *table)
     790              : {
     791            0 :     if (!table) return FALSE;
     792            0 :     return table->invisible;
     793              : }
     794              : 
     795           63 : Account * gncTaxTableEntryGetAccount (const GncTaxTableEntry *entry)
     796              : {
     797           63 :     if (!entry) return NULL;
     798           63 :     return entry->account;
     799              : }
     800              : 
     801          123 : GncAmountType gncTaxTableEntryGetType (const GncTaxTableEntry *entry)
     802              : {
     803          123 :     if (!entry) return 0;
     804          123 :     return entry->type;
     805              : }
     806              : 
     807          123 : gnc_numeric gncTaxTableEntryGetAmount (const GncTaxTableEntry *entry)
     808              : {
     809          123 :     if (!entry) return gnc_numeric_zero();
     810          123 :     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. */
     815            3 : GncTaxTable* gncTaxTableEntryGetTable( const GncTaxTableEntry* entry )
     816              : {
     817            3 :     if (!entry) return NULL;
     818            3 :     return entry->table;
     819              : }
     820              : 
     821            2 : int gncTaxTableEntryCompare (const GncTaxTableEntry *a, const GncTaxTableEntry *b)
     822              : {
     823              :     char *name_a, *name_b;
     824              :     int retval;
     825              : 
     826            2 :     if (!a && !b) return 0;
     827            2 :     if (!a) return -1;
     828            2 :     if (!b) return 1;
     829              : 
     830            2 :     name_a = gnc_account_get_full_name (a->account);
     831            2 :     name_b = gnc_account_get_full_name (b->account);
     832            2 :     retval = g_strcmp0(name_a, name_b);
     833            2 :     g_free(name_a);
     834            2 :     g_free(name_b);
     835              : 
     836            2 :     if (retval)
     837            2 :         return retval;
     838              : 
     839            0 :     return gnc_numeric_compare (a->amount, b->amount);
     840              : }
     841              : 
     842          137 : int gncTaxTableCompare (const GncTaxTable *a, const GncTaxTable *b)
     843              : {
     844          137 :     if (!a && !b) return 0;
     845          137 :     if (!a) return -1;
     846          137 :     if (!b) return 1;
     847          137 :     return g_strcmp0 (a->name, b->name);
     848              : }
     849              : 
     850            2 : gboolean gncTaxTableEntryEqual(const GncTaxTableEntry *a, const GncTaxTableEntry *b)
     851              : {
     852            2 :     if (a == NULL && b == NULL) return TRUE;
     853            2 :     if (a == NULL || b == NULL) return FALSE;
     854              : 
     855            2 :     if (!xaccAccountEqual(a->account, b->account, TRUE))
     856              :     {
     857            0 :         PWARN("accounts differ");
     858            0 :         return FALSE;
     859              :     }
     860              : 
     861            2 :     if (a->type != b->type)
     862              :     {
     863            0 :         PWARN("types differ");
     864            0 :         return FALSE;
     865              :     }
     866              : 
     867            2 :     if (!gnc_numeric_equal(a->amount, b->amount))
     868              :     {
     869            0 :         PWARN("amounts differ");
     870            0 :         return FALSE;
     871              :     }
     872              : 
     873            2 :     return TRUE;
     874              : }
     875              : 
     876            6 : gboolean gncTaxTableEqual(const GncTaxTable *a, const GncTaxTable *b)
     877              : {
     878            6 :     if (a == NULL && b == NULL) return TRUE;
     879            1 :     if (a == NULL || b == NULL) return FALSE;
     880              : 
     881            1 :     g_return_val_if_fail(GNC_IS_TAXTABLE(a), FALSE);
     882            1 :     g_return_val_if_fail(GNC_IS_TAXTABLE(b), FALSE);
     883              : 
     884            1 :     if (g_strcmp0(a->name, b->name) != 0)
     885              :     {
     886            0 :         PWARN("Names differ: %s vs %s", a->name, b->name);
     887            0 :         return FALSE;
     888              :     }
     889              : 
     890            1 :     if (a->invisible != b->invisible)
     891              :     {
     892            0 :         PWARN("invisible flags differ");
     893            0 :         return FALSE;
     894              :     }
     895              : 
     896            1 :     if ((a->entries != NULL) != (b->entries != NULL))
     897              :     {
     898            0 :         PWARN("only one has entries");
     899            0 :         return FALSE;
     900              :     }
     901              : 
     902            1 :     if (a->entries != NULL && b->entries != NULL)
     903              :     {
     904              :         GncTaxTableEntryList* a_node;
     905              :         GncTaxTableEntryList* b_node;
     906              : 
     907            1 :         for (a_node = a->entries, b_node = b->entries;
     908            3 :                 a_node != NULL && b_node != NULL;
     909            2 :                 a_node = a_node->next, b_node = b_node->next)
     910              :         {
     911            2 :             if (!gncTaxTableEntryEqual((GncTaxTableEntry*)a_node->data,
     912            2 :                                        (GncTaxTableEntry*)b_node->data))
     913              :             {
     914            0 :                 PWARN("entries differ");
     915            0 :                 return FALSE;
     916              :             }
     917              :         }
     918              : 
     919            1 :         if (a_node != NULL || b_node != NULL)
     920              :         {
     921            0 :             PWARN("Unequal number of entries");
     922            0 :             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            1 :     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              :  */
     942          422 : GList *gncAccountValueAdd (GList *list, Account *acc, gnc_numeric value)
     943              : {
     944              :     GList *li;
     945          422 :     GncAccountValue *res = NULL;
     946              : 
     947          422 :     g_return_val_if_fail (acc, list);
     948          422 :     g_return_val_if_fail (gnc_numeric_check (value) == GNC_ERROR_OK, list);
     949              : 
     950              :     /* Try to find the account in the list */
     951          427 :     for (li = list; li; li = li->next)
     952              :     {
     953          140 :         res = li->data;
     954          140 :         if (res->account == acc)
     955              :         {
     956          135 :             res->value = gnc_numeric_add (res->value, value, GNC_DENOM_AUTO,
     957              :                                           GNC_HOW_DENOM_REDUCE | GNC_HOW_RND_ROUND_HALF_UP);
     958          135 :             return list;
     959              :         }
     960              :     }
     961              :     /* Nope, didn't find it. */
     962              : 
     963          287 :     res = g_new0 (GncAccountValue, 1);
     964          287 :     res->account = acc;
     965          287 :     res->value = value;
     966          287 :     return g_list_prepend (list, res);
     967              : }
     968              : 
     969              : /* Merge l2 into l1.  l2 is not touched. */
     970          564 : GList *gncAccountValueAddList (GList *l1, GList *l2)
     971              : {
     972              :     GList *li;
     973              : 
     974          694 :     for (li = l2; li; li = li->next )
     975              :     {
     976          130 :         GncAccountValue *val = li->data;
     977          130 :         l1 = gncAccountValueAdd (l1, val->account, val->value);
     978              :     }
     979              : 
     980          564 :     return l1;
     981              : }
     982              : 
     983              : /* return the total for this list */
     984          316 : gnc_numeric gncAccountValueTotal (GList *list)
     985              : {
     986          316 :     gnc_numeric total = gnc_numeric_zero ();
     987              : 
     988          376 :     for ( ; list ; list = list->next)
     989              :     {
     990           60 :         GncAccountValue *val = list->data;
     991           60 :         total = gnc_numeric_add (total, val->value, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE | GNC_HOW_RND_ROUND_HALF_UP);
     992              :     }
     993          316 :     return total;
     994              : }
     995              : 
     996              : /* Destroy a list of accountvalues */
     997          891 : void gncAccountValueDestroy (GList *list)
     998              : {
     999              :     GList *node;
    1000         1149 :     for ( node = list; node ; node = node->next)
    1001          258 :         g_free (node->data);
    1002              : 
    1003          891 :     g_list_free (list);
    1004          891 : }
    1005              : 
    1006              : /* Package-Private functions */
    1007              : 
    1008          431 : static void _gncTaxTableCreate (QofBook *book)
    1009              : {
    1010              :     struct _book_info *bi;
    1011              : 
    1012          431 :     if (!book) return;
    1013              : 
    1014          431 :     bi = g_new0 (struct _book_info, 1);
    1015          431 :     qof_book_set_data (book, _GNC_MOD_NAME, bi);
    1016              : }
    1017              : 
    1018              : static void
    1019            6 : destroy_taxtable_on_book_close (QofInstance *ent, gpointer data)
    1020              : {
    1021            6 :     GncTaxTable *table = GNC_TAXTABLE(ent);
    1022              : 
    1023            6 :     gncTaxTableBeginEdit (table);
    1024            6 :     gncTaxTableDestroy (table);
    1025            6 : }
    1026              : 
    1027          301 : static void _gncTaxTableDestroy (QofBook *book)
    1028              : {
    1029              :     struct _book_info *bi;
    1030              :     QofCollection *col;
    1031              : 
    1032          301 :     if (!book) return;
    1033              : 
    1034          301 :     bi = qof_book_get_data (book, _GNC_MOD_NAME);
    1035              : 
    1036          301 :     col = qof_book_get_collection (book, GNC_ID_TAXTABLE);
    1037          301 :     qof_collection_foreach (col, destroy_taxtable_on_book_close, NULL);
    1038              : 
    1039          301 :     g_list_free (bi->tables);
    1040          301 :     g_free (bi);
    1041              : }
    1042              : 
    1043              : static 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              : 
    1058           84 : gboolean 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           84 :     qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncTaxTableCompare, params);
    1070              : 
    1071           84 :     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);
        

Generated by: LCOV version 2.0-1