LCOV - code coverage report
Current view: top level - libgnucash/backend/xml - gnc-bill-term-xml-v2.cpp (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 13.4 % 313 42
Test Date: 2025-02-07 16:25:45 Functions: 19.0 % 42 8
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /********************************************************************\
       2                 :             :  * gnc-bill-term-xml-v2.c -- billing term xml i/o implementation    *
       3                 :             :  *                                                                  *
       4                 :             :  * Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU>                *
       5                 :             :  *                                                                  *
       6                 :             :  * This program is free software; you can redistribute it and/or    *
       7                 :             :  * modify it under the terms of the GNU General Public License as   *
       8                 :             :  * published by the Free Software Foundation; either version 2 of   *
       9                 :             :  * the License, or (at your option) any later version.              *
      10                 :             :  *                                                                  *
      11                 :             :  * This program is distributed in the hope that it will be useful,  *
      12                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
      13                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
      14                 :             :  * GNU General Public License for more details.                     *
      15                 :             :  *                                                                  *
      16                 :             :  * You should have received a copy of the GNU General Public License*
      17                 :             :  * along with this program; if not, contact:                        *
      18                 :             :  *                                                                  *
      19                 :             :  * Free Software Foundation           Voice:  +1-617-542-5942       *
      20                 :             :  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
      21                 :             :  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
      22                 :             :  *                                                                  *
      23                 :             : \********************************************************************/
      24                 :             : #include <config.h>
      25                 :             : #include <stdlib.h>
      26                 :             : #include <string.h>
      27                 :             : 
      28                 :             : #include "gncBillTermP.h"
      29                 :             : #include "gncInvoice.h"
      30                 :             : #include "qof.h"
      31                 :             : 
      32                 :             : #include "gnc-xml-helper.h"
      33                 :             : 
      34                 :             : #include "sixtp.h"
      35                 :             : #include "sixtp-utils.h"
      36                 :             : #include "sixtp-parsers.h"
      37                 :             : #include "sixtp-utils.h"
      38                 :             : #include "sixtp-dom-parsers.h"
      39                 :             : #include "sixtp-dom-generators.h"
      40                 :             : 
      41                 :             : #include "gnc-xml.h"
      42                 :             : #include "io-gncxml-gen.h"
      43                 :             : #include "io-gncxml-v2.h"
      44                 :             : #include "gnc-bill-term-xml-v2.h"
      45                 :             : 
      46                 :             : #include "xml-helpers.h"
      47                 :             : 
      48                 :             : #define _GNC_MOD_NAME   GNC_ID_BILLTERM
      49                 :             : 
      50                 :             : static QofLogModule log_module = GNC_MOD_IO;
      51                 :             : 
      52                 :             : const gchar* billterm_version_string = "2.0.0";
      53                 :             : 
      54                 :             : /* ids */
      55                 :             : #define gnc_billterm_string "gnc:GncBillTerm"
      56                 :             : #define billterm_guid_string "billterm:guid"
      57                 :             : #define billterm_name_string "billterm:name"
      58                 :             : #define billterm_desc_string "billterm:desc"
      59                 :             : #define billterm_refcount_string "billterm:refcount"
      60                 :             : #define billterm_invisible_string "billterm:invisible"
      61                 :             : #define billterm_parent_string "billterm:parent"
      62                 :             : #define billterm_child_string "billterm:child"
      63                 :             : #define billterm_slots_string "billterm:slots"
      64                 :             : 
      65                 :             : #define gnc_daystype_string "billterm:days"
      66                 :             : #define days_duedays_string "bt-days:due-days"
      67                 :             : #define days_discdays_string "bt-days:disc-days"
      68                 :             : #define days_discount_string "bt-days:discount"
      69                 :             : 
      70                 :             : #define gnc_proximotype_string "billterm:proximo"
      71                 :             : #define prox_dueday_string "bt-prox:due-day"
      72                 :             : #define prox_discday_string "bt-prox:disc-day"
      73                 :             : #define prox_discount_string "bt-prox:discount"
      74                 :             : #define prox_cutoff_string "bt-prox:cutoff-day"
      75                 :             : 
      76                 :             : static xmlNodePtr
      77                 :           0 : billterm_dom_tree_create (GncBillTerm* term)
      78                 :             : {
      79                 :             :     xmlNodePtr ret, data;
      80                 :             : 
      81                 :           0 :     ret = xmlNewNode (NULL, BAD_CAST gnc_billterm_string);
      82                 :           0 :     xmlSetProp (ret, BAD_CAST "version", BAD_CAST billterm_version_string);
      83                 :             : 
      84                 :           0 :     maybe_add_guid (ret, billterm_guid_string, QOF_INSTANCE (term));
      85                 :           0 :     xmlAddChild (ret, text_to_dom_tree (billterm_name_string,
      86                 :             :                                         gncBillTermGetName (term)));
      87                 :           0 :     xmlAddChild (ret, text_to_dom_tree (billterm_desc_string,
      88                 :             :                                         gncBillTermGetDescription (term)));
      89                 :             : 
      90                 :           0 :     xmlAddChild (ret, int_to_dom_tree (billterm_refcount_string,
      91                 :             :                                        gncBillTermGetRefcount (term)));
      92                 :           0 :     xmlAddChild (ret, int_to_dom_tree (billterm_invisible_string,
      93                 :           0 :                                        gncBillTermGetInvisible (term)));
      94                 :             : 
      95                 :             :     /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
      96                 :           0 :     xmlAddChild (ret, qof_instance_slots_to_dom_tree (billterm_slots_string,
      97                 :           0 :                                                       QOF_INSTANCE (term)));
      98                 :             : 
      99                 :             :     /* We should not be our own child */
     100                 :           0 :     if (gncBillTermGetChild (term) != term)
     101                 :           0 :         maybe_add_guid (ret, billterm_child_string,
     102                 :           0 :                         QOF_INSTANCE (gncBillTermGetChild (term)));
     103                 :             : 
     104                 :           0 :     maybe_add_guid (ret, billterm_parent_string,
     105                 :           0 :                     QOF_INSTANCE (gncBillTermGetParent (term)));
     106                 :             : 
     107                 :           0 :     switch (gncBillTermGetType (term))
     108                 :             :     {
     109                 :           0 :     case GNC_TERM_TYPE_DAYS:
     110                 :           0 :         data = xmlNewChild (ret, NULL, BAD_CAST gnc_daystype_string, NULL);
     111                 :           0 :         maybe_add_int (data, days_duedays_string, gncBillTermGetDueDays (term));
     112                 :           0 :         maybe_add_int (data, days_discdays_string,
     113                 :             :                        gncBillTermGetDiscountDays (term));
     114                 :           0 :         maybe_add_numeric (data, days_discount_string,
     115                 :             :                            gncBillTermGetDiscount (term));
     116                 :           0 :         break;
     117                 :             : 
     118                 :           0 :     case GNC_TERM_TYPE_PROXIMO:
     119                 :           0 :         data = xmlNewChild (ret, NULL, BAD_CAST gnc_proximotype_string, NULL);
     120                 :           0 :         maybe_add_int (data, prox_dueday_string, gncBillTermGetDueDays (term));
     121                 :           0 :         maybe_add_int (data, prox_discday_string,
     122                 :             :                        gncBillTermGetDiscountDays (term));
     123                 :           0 :         maybe_add_numeric (data, prox_discount_string,
     124                 :             :                            gncBillTermGetDiscount (term));
     125                 :           0 :         maybe_add_int (data, prox_cutoff_string, gncBillTermGetCutoff (term));
     126                 :           0 :         break;
     127                 :             :     }
     128                 :             : 
     129                 :           0 :     return ret;
     130                 :             : }
     131                 :             : 
     132                 :             : /***********************************************************************/
     133                 :             : 
     134                 :             : struct billterm_pdata
     135                 :             : {
     136                 :             :     GncBillTerm* term;
     137                 :             :     QofBook* book;
     138                 :             : };
     139                 :             : 
     140                 :             : static gboolean
     141                 :           0 : set_int (xmlNodePtr node, GncBillTerm* term,
     142                 :             :          void (*func) (GncBillTerm*, gint))
     143                 :             : {
     144                 :             :     gint64 val;
     145                 :           0 :     dom_tree_to_integer (node, &val);
     146                 :           0 :     func (term, val);
     147                 :           0 :     return TRUE;
     148                 :             : }
     149                 :             : 
     150                 :             : static gboolean
     151                 :           0 : set_numeric (xmlNodePtr node, GncBillTerm* term,
     152                 :             :              void (*func) (GncBillTerm*, gnc_numeric))
     153                 :             : {
     154                 :           0 :     func (term, dom_tree_to_gnc_numeric (node));
     155                 :           0 :     return TRUE;
     156                 :             : }
     157                 :             : 
     158                 :             : /***********************************************************************/
     159                 :             : 
     160                 :             : static gboolean
     161                 :           0 : days_duedays_handler (xmlNodePtr node, gpointer billterm_pdata)
     162                 :             : {
     163                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     164                 :           0 :     return set_int (node, pdata->term, gncBillTermSetDueDays);
     165                 :             : }
     166                 :             : 
     167                 :             : static gboolean
     168                 :           0 : days_discdays_handler (xmlNodePtr node, gpointer billterm_pdata)
     169                 :             : {
     170                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     171                 :           0 :     return set_int (node, pdata->term, gncBillTermSetDiscountDays);
     172                 :             : }
     173                 :             : 
     174                 :             : static gboolean
     175                 :           0 : days_discount_handler (xmlNodePtr node, gpointer billterm_pdata)
     176                 :             : {
     177                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     178                 :           0 :     return set_numeric (node, pdata->term, gncBillTermSetDiscount);
     179                 :             : }
     180                 :             : 
     181                 :             : static struct dom_tree_handler days_data_handlers_v2[] =
     182                 :             : {
     183                 :             :     { days_duedays_string, days_duedays_handler, 0, 0 },
     184                 :             :     { days_discdays_string, days_discdays_handler, 0, 0 },
     185                 :             :     { days_discount_string, days_discount_handler, 0, 0 },
     186                 :             :     { NULL, 0, 0, 0 }
     187                 :             : };
     188                 :             : 
     189                 :             : static gboolean
     190                 :           0 : dom_tree_to_days_data (xmlNodePtr node, struct billterm_pdata* pdata)
     191                 :             : {
     192                 :             :     gboolean successful;
     193                 :             : 
     194                 :           0 :     successful = dom_tree_generic_parse (node, days_data_handlers_v2, pdata);
     195                 :             : 
     196                 :           0 :     if (!successful)
     197                 :           0 :         PERR ("failed to parse billing term days data");
     198                 :             : 
     199                 :           0 :     return successful;
     200                 :             : }
     201                 :             : 
     202                 :             : /***********************************************************************/
     203                 :             : 
     204                 :             : static gboolean
     205                 :           0 : prox_dueday_handler (xmlNodePtr node, gpointer billterm_pdata)
     206                 :             : {
     207                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     208                 :           0 :     return set_int (node, pdata->term, gncBillTermSetDueDays);
     209                 :             : }
     210                 :             : 
     211                 :             : static gboolean
     212                 :           0 : prox_discday_handler (xmlNodePtr node, gpointer billterm_pdata)
     213                 :             : {
     214                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     215                 :           0 :     return set_int (node, pdata->term, gncBillTermSetDiscountDays);
     216                 :             : }
     217                 :             : 
     218                 :             : static gboolean
     219                 :           0 : prox_discount_handler (xmlNodePtr node, gpointer billterm_pdata)
     220                 :             : {
     221                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     222                 :           0 :     return set_numeric (node, pdata->term, gncBillTermSetDiscount);
     223                 :             : }
     224                 :             : 
     225                 :             : static gboolean
     226                 :           0 : prox_cutoff_handler (xmlNodePtr node, gpointer billterm_pdata)
     227                 :             : {
     228                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     229                 :           0 :     return set_int (node, pdata->term, gncBillTermSetCutoff);
     230                 :             : }
     231                 :             : 
     232                 :             : static struct dom_tree_handler prox_data_handlers_v2[] =
     233                 :             : {
     234                 :             :     { prox_dueday_string, prox_dueday_handler, 0, 0 },
     235                 :             :     { prox_discday_string, prox_discday_handler, 0, 0 },
     236                 :             :     { prox_discount_string, prox_discount_handler, 0, 0 },
     237                 :             :     { prox_cutoff_string, prox_cutoff_handler, 0, 0 },
     238                 :             :     { NULL, 0, 0, 0 }
     239                 :             : };
     240                 :             : 
     241                 :             : static gboolean
     242                 :           0 : dom_tree_to_prox_data (xmlNodePtr node, struct billterm_pdata* pdata)
     243                 :             : {
     244                 :             :     gboolean successful;
     245                 :             : 
     246                 :           0 :     successful = dom_tree_generic_parse (node, prox_data_handlers_v2, pdata);
     247                 :             : 
     248                 :           0 :     if (!successful)
     249                 :           0 :         PERR ("failed to parse billing term prox data");
     250                 :             : 
     251                 :           0 :     return successful;
     252                 :             : }
     253                 :             : 
     254                 :             : /***********************************************************************/
     255                 :             : 
     256                 :             : static gboolean
     257                 :           0 : set_parent_child (xmlNodePtr node, struct billterm_pdata* pdata,
     258                 :             :                   void (*func) (GncBillTerm*, GncBillTerm*))
     259                 :             : {
     260                 :             :     GncGUID* guid;
     261                 :             :     GncBillTerm* term;
     262                 :             : 
     263                 :           0 :     guid = dom_tree_to_guid (node);
     264                 :           0 :     g_return_val_if_fail (guid, FALSE);
     265                 :           0 :     term = gncBillTermLookup (pdata->book, guid);
     266                 :           0 :     if (!term)
     267                 :             :     {
     268                 :           0 :         term = gncBillTermCreate (pdata->book);
     269                 :           0 :         gncBillTermBeginEdit (term);
     270                 :           0 :         gncBillTermSetGUID (term, guid);
     271                 :           0 :         gncBillTermCommitEdit (term);
     272                 :             :     }
     273                 :           0 :     guid_free (guid);
     274                 :           0 :     g_return_val_if_fail (term, FALSE);
     275                 :           0 :     func (pdata->term, term);
     276                 :             : 
     277                 :           0 :     return TRUE;
     278                 :             : }
     279                 :             : 
     280                 :             : static gboolean
     281                 :           0 : set_string (xmlNodePtr node, GncBillTerm* term,
     282                 :             :             void (*func) (GncBillTerm*, const char*))
     283                 :             : {
     284                 :           0 :     char* txt = dom_tree_to_text (node);
     285                 :           0 :     g_return_val_if_fail (txt, FALSE);
     286                 :           0 :     func (term, txt);
     287                 :           0 :     g_free (txt);
     288                 :           0 :     return TRUE;
     289                 :             : }
     290                 :             : 
     291                 :             : static gboolean
     292                 :           0 : billterm_guid_handler (xmlNodePtr node, gpointer billterm_pdata)
     293                 :             : {
     294                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     295                 :             :     GncGUID* guid;
     296                 :             :     GncBillTerm* term;
     297                 :             : 
     298                 :           0 :     guid = dom_tree_to_guid (node);
     299                 :           0 :     g_return_val_if_fail (guid, FALSE);
     300                 :           0 :     term = gncBillTermLookup (pdata->book, guid);
     301                 :           0 :     if (term)
     302                 :             :     {
     303                 :           0 :         gncBillTermDestroy (pdata->term);
     304                 :           0 :         pdata->term = term;
     305                 :           0 :         gncBillTermBeginEdit (term);
     306                 :             :     }
     307                 :             :     else
     308                 :             :     {
     309                 :           0 :         gncBillTermSetGUID (pdata->term, guid);
     310                 :             :     }
     311                 :             : 
     312                 :           0 :     guid_free (guid);
     313                 :             : 
     314                 :           0 :     return TRUE;
     315                 :             : }
     316                 :             : 
     317                 :             : static gboolean
     318                 :           0 : billterm_name_handler (xmlNodePtr node, gpointer billterm_pdata)
     319                 :             : {
     320                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     321                 :           0 :     return set_string (node, pdata->term, gncBillTermSetName);
     322                 :             : }
     323                 :             : 
     324                 :             : static gboolean
     325                 :           0 : billterm_desc_handler (xmlNodePtr node, gpointer billterm_pdata)
     326                 :             : {
     327                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     328                 :           0 :     return set_string (node, pdata->term, gncBillTermSetDescription);
     329                 :             : }
     330                 :             : 
     331                 :             : static gboolean
     332                 :           0 : billterm_refcount_handler (xmlNodePtr node, gpointer billterm_pdata)
     333                 :             : {
     334                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     335                 :             :     gint64 val;
     336                 :             : 
     337                 :           0 :     dom_tree_to_integer (node, &val);
     338                 :           0 :     gncBillTermSetRefcount (pdata->term, val);
     339                 :           0 :     return TRUE;
     340                 :             : }
     341                 :             : 
     342                 :             : static gboolean
     343                 :           0 : billterm_invisible_handler (xmlNodePtr node, gpointer billterm_pdata)
     344                 :             : {
     345                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     346                 :             :     gint64 val;
     347                 :             : 
     348                 :           0 :     dom_tree_to_integer (node, &val);
     349                 :           0 :     if (val)
     350                 :           0 :         gncBillTermMakeInvisible (pdata->term);
     351                 :           0 :     return TRUE;
     352                 :             : }
     353                 :             : 
     354                 :             : static gboolean
     355                 :           0 : billterm_parent_handler (xmlNodePtr node, gpointer billterm_pdata)
     356                 :             : {
     357                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     358                 :           0 :     return set_parent_child (node, pdata, gncBillTermSetParent);
     359                 :             : }
     360                 :             : 
     361                 :             : static gboolean
     362                 :           0 : billterm_child_handler (xmlNodePtr node, gpointer billterm_pdata)
     363                 :             : {
     364                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     365                 :           0 :     return set_parent_child (node, pdata, gncBillTermSetChild);
     366                 :             : }
     367                 :             : 
     368                 :             : static gboolean
     369                 :           0 : billterm_days_data_handler (xmlNodePtr node, gpointer billterm_pdata)
     370                 :             : {
     371                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     372                 :             : 
     373                 :           0 :     g_return_val_if_fail (node, FALSE);
     374                 :           0 :     g_return_val_if_fail (gncBillTermGetType (pdata->term) == 0, FALSE);
     375                 :             : 
     376                 :           0 :     gncBillTermSetType (pdata->term, GNC_TERM_TYPE_DAYS);
     377                 :           0 :     return dom_tree_to_days_data (node, pdata);
     378                 :             : }
     379                 :             : 
     380                 :             : static gboolean
     381                 :           0 : billterm_prox_data_handler (xmlNodePtr node, gpointer billterm_pdata)
     382                 :             : {
     383                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     384                 :             : 
     385                 :           0 :     g_return_val_if_fail (node, FALSE);
     386                 :           0 :     g_return_val_if_fail (gncBillTermGetType (pdata->term) == 0, FALSE);
     387                 :             : 
     388                 :           0 :     gncBillTermSetType (pdata->term, GNC_TERM_TYPE_PROXIMO);
     389                 :           0 :     return dom_tree_to_prox_data (node, pdata);
     390                 :             : }
     391                 :             : 
     392                 :             : static gboolean
     393                 :           0 : billterm_slots_handler (xmlNodePtr node, gpointer billterm_pdata)
     394                 :             : {
     395                 :           0 :     struct billterm_pdata* pdata = static_cast<decltype (pdata)> (billterm_pdata);
     396                 :           0 :     return dom_tree_create_instance_slots (node, QOF_INSTANCE (pdata->term));
     397                 :             : }
     398                 :             : 
     399                 :             : static struct dom_tree_handler billterm_handlers_v2[] =
     400                 :             : {
     401                 :             :     { billterm_guid_string, billterm_guid_handler, 1, 0 },
     402                 :             :     { billterm_name_string, billterm_name_handler, 1, 0 },
     403                 :             :     { billterm_desc_string, billterm_desc_handler, 1, 0 },
     404                 :             :     { billterm_refcount_string, billterm_refcount_handler, 1, 0 },
     405                 :             :     { billterm_invisible_string, billterm_invisible_handler, 1, 0 },
     406                 :             :     { billterm_parent_string, billterm_parent_handler, 0, 0 },
     407                 :             :     { billterm_child_string, billterm_child_handler, 0, 0 },
     408                 :             :     { billterm_slots_string, billterm_slots_handler, 0, 0 },
     409                 :             :     { gnc_daystype_string, billterm_days_data_handler, 0, 0 },
     410                 :             :     { gnc_proximotype_string, billterm_prox_data_handler, 0, 0 },
     411                 :             :     { NULL, 0, 0, 0 }
     412                 :             : };
     413                 :             : 
     414                 :             : static GncBillTerm*
     415                 :           0 : dom_tree_to_billterm (xmlNodePtr node, QofBook* book)
     416                 :             : {
     417                 :             :     struct billterm_pdata billterm_pdata;
     418                 :             :     gboolean successful;
     419                 :             : 
     420                 :           0 :     billterm_pdata.term = gncBillTermCreate (book);
     421                 :           0 :     billterm_pdata.book = book;
     422                 :           0 :     gncBillTermBeginEdit (billterm_pdata.term);
     423                 :             : 
     424                 :           0 :     successful = dom_tree_generic_parse (node, billterm_handlers_v2,
     425                 :             :                                          &billterm_pdata);
     426                 :             : 
     427                 :           0 :     if (successful)
     428                 :             :     {
     429                 :           0 :         gncBillTermCommitEdit (billterm_pdata.term);
     430                 :             :     }
     431                 :             :     else
     432                 :             :     {
     433                 :           0 :         PERR ("failed to parse billing term tree");
     434                 :           0 :         gncBillTermDestroy (billterm_pdata.term);
     435                 :           0 :         billterm_pdata.term = NULL;
     436                 :             :     }
     437                 :             : 
     438                 :           0 :     return billterm_pdata.term;
     439                 :             : }
     440                 :             : 
     441                 :             : static gboolean
     442                 :           0 : gnc_billterm_end_handler (gpointer data_for_children,
     443                 :             :                           GSList* data_from_children, GSList* sibling_data,
     444                 :             :                           gpointer parent_data, gpointer global_data,
     445                 :             :                           gpointer* result, const gchar* tag)
     446                 :             : {
     447                 :             :     GncBillTerm* term;
     448                 :           0 :     xmlNodePtr tree = (xmlNodePtr)data_for_children;
     449                 :           0 :     gxpf_data* gdata = (gxpf_data*)global_data;
     450                 :           0 :     QofBook* book = static_cast<decltype (book)> (gdata->bookdata);
     451                 :             : 
     452                 :             : 
     453                 :           0 :     if (parent_data)
     454                 :             :     {
     455                 :           0 :         return TRUE;
     456                 :             :     }
     457                 :             : 
     458                 :             :     /* OK.  For some messed up reason this is getting called again with a
     459                 :             :        NULL tag.  So we ignore those cases */
     460                 :           0 :     if (!tag)
     461                 :             :     {
     462                 :           0 :         return TRUE;
     463                 :             :     }
     464                 :             : 
     465                 :           0 :     g_return_val_if_fail (tree, FALSE);
     466                 :             : 
     467                 :           0 :     term = dom_tree_to_billterm (tree, book);
     468                 :           0 :     if (term != NULL)
     469                 :             :     {
     470                 :           0 :         gdata->cb (tag, gdata->parsedata, term);
     471                 :             :     }
     472                 :             : 
     473                 :           0 :     xmlFreeNode (tree);
     474                 :             : 
     475                 :           0 :     return term != NULL;
     476                 :             : }
     477                 :             : 
     478                 :             : static sixtp*
     479                 :          21 : billterm_sixtp_parser_create (void)
     480                 :             : {
     481                 :          21 :     return sixtp_dom_parser_new (gnc_billterm_end_handler, NULL, NULL);
     482                 :             : }
     483                 :             : 
     484                 :             : static void
     485                 :           0 : do_count (QofInstance* term_p, gpointer count_p)
     486                 :             : {
     487                 :           0 :     int* count = static_cast<decltype (count)> (count_p);
     488                 :           0 :     (*count)++;
     489                 :           0 : }
     490                 :             : 
     491                 :             : static int
     492                 :           4 : billterm_get_count (QofBook* book)
     493                 :             : {
     494                 :           4 :     int count = 0;
     495                 :           4 :     qof_object_foreach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
     496                 :           4 :     return count;
     497                 :             : }
     498                 :             : 
     499                 :             : static void
     500                 :           0 : xml_add_billterm (QofInstance* term_p, gpointer out_p)
     501                 :             : {
     502                 :             :     xmlNodePtr node;
     503                 :           0 :     GncBillTerm* term = (GncBillTerm*) term_p;
     504                 :           0 :     FILE* out = static_cast<decltype (out)> (out_p);
     505                 :             : 
     506                 :           0 :     if (ferror (out))
     507                 :           0 :         return;
     508                 :             : 
     509                 :           0 :     node = billterm_dom_tree_create (term);
     510                 :           0 :     xmlElemDump (out, NULL, node);
     511                 :           0 :     xmlFreeNode (node);
     512                 :           0 :     if (ferror (out) || fprintf (out, "\n") < 0)
     513                 :           0 :         return;
     514                 :             : }
     515                 :             : 
     516                 :             : static gboolean
     517                 :           4 : billterm_write (FILE* out, QofBook* book)
     518                 :             : {
     519                 :           4 :     qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_billterm,
     520                 :             :                                (gpointer) out);
     521                 :           4 :     return ferror (out) == 0;
     522                 :             : }
     523                 :             : 
     524                 :             : static gboolean
     525                 :           0 : billterm_is_grandchild (GncBillTerm* term)
     526                 :             : {
     527                 :           0 :     return (gncBillTermGetParent (gncBillTermGetParent (term)) != NULL);
     528                 :             : }
     529                 :             : 
     530                 :             : static GncBillTerm*
     531                 :           0 : billterm_find_senior (GncBillTerm* term)
     532                 :             : {
     533                 :           0 :     GncBillTerm* temp, *parent, *gp = NULL;
     534                 :             : 
     535                 :           0 :     temp = term;
     536                 :             :     do
     537                 :             :     {
     538                 :             :         /* See if "temp" is a grandchild */
     539                 :           0 :         parent = gncBillTermGetParent (temp);
     540                 :           0 :         if (!parent)
     541                 :           0 :             break;
     542                 :           0 :         gp = gncBillTermGetParent (parent);
     543                 :           0 :         if (!gp)
     544                 :           0 :             break;
     545                 :             : 
     546                 :             :         /* Yep, this is a grandchild.  Move up one generation and try again */
     547                 :           0 :         temp = parent;
     548                 :             :     }
     549                 :             :     while (TRUE);
     550                 :             : 
     551                 :             :     /* Ok, at this point temp points to the most senior child and parent
     552                 :             :      * should point to the top billterm (and gp should be NULL).  If
     553                 :             :      * parent is NULL then we are the most senior child (and have no
     554                 :             :      * children), so do nothing.  If temp == term then there is no
     555                 :             :      * grandparent, so do nothing.
     556                 :             :      *
     557                 :             :      * Do something if parent != NULL && temp != term
     558                 :             :      */
     559                 :           0 :     g_assert (gp == NULL);
     560                 :             : 
     561                 :             :     /* return the most senior term */
     562                 :           0 :     return temp;
     563                 :             : }
     564                 :             : 
     565                 :             : /* build a list of bill terms that are grandchildren or bogus (empty entry list). */
     566                 :             : static void
     567                 :           0 : billterm_scrub_cb (QofInstance* term_p, gpointer list_p)
     568                 :             : {
     569                 :           0 :     GncBillTerm* term = GNC_BILLTERM (term_p);
     570                 :           0 :     GList** list = static_cast<decltype (list)> (list_p);
     571                 :             : 
     572                 :           0 :     if (billterm_is_grandchild (term))
     573                 :             :     {
     574                 :           0 :         *list = g_list_prepend (*list, term);
     575                 :             : 
     576                 :             :     }
     577                 :           0 :     else if (!gncBillTermGetType (term))
     578                 :             :     {
     579                 :           0 :         GncBillTerm* t = gncBillTermGetParent (term);
     580                 :           0 :         if (t)
     581                 :             :         {
     582                 :             :             /* Fix up the broken "copy" function */
     583                 :             :             gchar guidstr[GUID_ENCODING_LENGTH + 1];
     584                 :           0 :             guid_to_string_buff (qof_instance_get_guid (QOF_INSTANCE (term)), guidstr);
     585                 :           0 :             PWARN ("Fixing broken child billterm: %s", guidstr);
     586                 :             : 
     587                 :           0 :             gncBillTermBeginEdit (term);
     588                 :           0 :             gncBillTermSetType (term, gncBillTermGetType (t));
     589                 :           0 :             gncBillTermSetDueDays (term, gncBillTermGetDueDays (t));
     590                 :           0 :             gncBillTermSetDiscountDays (term, gncBillTermGetDiscountDays (t));
     591                 :           0 :             gncBillTermSetDiscount (term, gncBillTermGetDiscount (t));
     592                 :           0 :             gncBillTermSetCutoff (term, gncBillTermGetCutoff (t));
     593                 :           0 :             gncBillTermCommitEdit (term);
     594                 :             : 
     595                 :             :         }
     596                 :             :         else
     597                 :             :         {
     598                 :             :             /* No parent?  Must be a standalone */
     599                 :           0 :             *list = g_list_prepend (*list, term);
     600                 :             :         }
     601                 :             :     }
     602                 :           0 : }
     603                 :             : 
     604                 :             : /* for each invoice, check the bill terms.  If the bill terms are
     605                 :             :  * grandchildren, then fix them to point to the most senior child
     606                 :             :  */
     607                 :             : static void
     608                 :           3 : billterm_scrub_invoices (QofInstance* invoice_p, gpointer ht_p)
     609                 :             : {
     610                 :           3 :     GHashTable* ht = static_cast<decltype (ht)> (ht_p);
     611                 :           3 :     GncInvoice* invoice = GNC_INVOICE (invoice_p);
     612                 :             :     GncBillTerm* term, *new_bt;
     613                 :             :     gint32 count;
     614                 :             : 
     615                 :           3 :     term = gncInvoiceGetTerms (invoice);
     616                 :           3 :     if (term)
     617                 :             :     {
     618                 :           0 :         if (billterm_is_grandchild (term))
     619                 :             :         {
     620                 :             :             gchar guidstr[GUID_ENCODING_LENGTH + 1];
     621                 :           0 :             guid_to_string_buff (qof_instance_get_guid (QOF_INSTANCE (invoice)), guidstr);
     622                 :           0 :             PWARN ("Fixing i-billterm on invoice %s\n", guidstr);
     623                 :           0 :             new_bt = billterm_find_senior (term);
     624                 :           0 :             gncInvoiceBeginEdit (invoice);
     625                 :           0 :             gncInvoiceSetTerms (invoice, new_bt);
     626                 :           0 :             gncInvoiceCommitEdit (invoice);
     627                 :           0 :             term = new_bt;
     628                 :             :         }
     629                 :           0 :         if (term)
     630                 :             :         {
     631                 :           0 :             count = GPOINTER_TO_INT (g_hash_table_lookup (ht, term));
     632                 :           0 :             count++;
     633                 :           0 :             g_hash_table_insert (ht, term, GINT_TO_POINTER (count));
     634                 :             :         }
     635                 :             :     }
     636                 :           3 : }
     637                 :             : 
     638                 :             : static void
     639                 :           0 : billterm_scrub_cust (QofInstance* cust_p, gpointer ht_p)
     640                 :             : {
     641                 :           0 :     GHashTable* ht = static_cast<decltype (ht)> (ht_p);
     642                 :           0 :     GncCustomer* cust = GNC_CUSTOMER (cust_p);
     643                 :             :     GncBillTerm* term;
     644                 :             :     gint32 count;
     645                 :             : 
     646                 :           0 :     term = gncCustomerGetTerms (cust);
     647                 :           0 :     if (term)
     648                 :             :     {
     649                 :           0 :         count = GPOINTER_TO_INT (g_hash_table_lookup (ht, term));
     650                 :           0 :         count++;
     651                 :           0 :         g_hash_table_insert (ht, term, GINT_TO_POINTER (count));
     652                 :           0 :         if (billterm_is_grandchild (term))
     653                 :             :         {
     654                 :             :             gchar custstr[GUID_ENCODING_LENGTH + 1];
     655                 :             :             gchar termstr[GUID_ENCODING_LENGTH + 1];
     656                 :           0 :             guid_to_string_buff (qof_instance_get_guid (QOF_INSTANCE (cust)), custstr);
     657                 :           0 :             guid_to_string_buff (qof_instance_get_guid (QOF_INSTANCE (term)), termstr);
     658                 :           0 :             PWARN ("customer %s has grandchild billterm %s\n", custstr, termstr);
     659                 :             :         }
     660                 :             :     }
     661                 :           0 : }
     662                 :             : 
     663                 :             : static void
     664                 :           3 : billterm_scrub_vendor (QofInstance* vendor_p, gpointer ht_p)
     665                 :             : {
     666                 :           3 :     GHashTable* ht = static_cast<decltype (ht)> (ht_p);
     667                 :           3 :     GncVendor* vendor = GNC_VENDOR (vendor_p);
     668                 :             :     GncBillTerm* term;
     669                 :             :     gint32 count;
     670                 :             : 
     671                 :           3 :     term = gncVendorGetTerms (vendor);
     672                 :           3 :     if (term)
     673                 :             :     {
     674                 :           0 :         count = GPOINTER_TO_INT (g_hash_table_lookup (ht, term));
     675                 :           0 :         count++;
     676                 :           0 :         g_hash_table_insert (ht, term, GINT_TO_POINTER (count));
     677                 :           0 :         if (billterm_is_grandchild (term))
     678                 :             :         {
     679                 :             :             gchar vendstr[GUID_ENCODING_LENGTH + 1];
     680                 :             :             gchar termstr[GUID_ENCODING_LENGTH + 1];
     681                 :           0 :             guid_to_string_buff (qof_instance_get_guid (QOF_INSTANCE (vendor)), vendstr);
     682                 :           0 :             guid_to_string_buff (qof_instance_get_guid (QOF_INSTANCE (term)), termstr);
     683                 :           0 :             PWARN ("vendor %s has grandchild billterm %s\n", vendstr, termstr);
     684                 :             :         }
     685                 :             :     }
     686                 :           3 : }
     687                 :             : 
     688                 :             : static void
     689                 :           0 : billterm_reset_refcount (gpointer key, gpointer value, gpointer notused)
     690                 :             : {
     691                 :           0 :     GncBillTerm* term = static_cast<decltype (term)> (key);
     692                 :           0 :     gint32 count = GPOINTER_TO_INT (value);
     693                 :             : 
     694                 :           0 :     if (count != gncBillTermGetRefcount (term) && !gncBillTermGetInvisible (term))
     695                 :             :     {
     696                 :             :         gchar termstr[GUID_ENCODING_LENGTH + 1];
     697                 :           0 :         guid_to_string_buff (qof_instance_get_guid (QOF_INSTANCE (term)), termstr);
     698                 :           0 :         PWARN ("Fixing refcount on billterm %s (%" G_GINT64_FORMAT " -> %d)\n",
     699                 :             :                termstr, gncBillTermGetRefcount (term), count);
     700                 :           0 :         gncBillTermSetRefcount (term, count);
     701                 :             :     }
     702                 :           0 : }
     703                 :             : 
     704                 :             : static void
     705                 :          21 : billterm_scrub (QofBook* book)
     706                 :             : {
     707                 :          21 :     GList* list = NULL;
     708                 :             :     GList* node;
     709                 :             :     GncBillTerm* parent, *term;
     710                 :          21 :     GHashTable* ht = g_hash_table_new (g_direct_hash, g_direct_equal);
     711                 :             : 
     712                 :          21 :     DEBUG ("scrubbing billterms...");
     713                 :          21 :     qof_object_foreach (GNC_ID_INVOICE,  book, billterm_scrub_invoices, ht);
     714                 :          21 :     qof_object_foreach (GNC_ID_CUSTOMER, book, billterm_scrub_cust, ht);
     715                 :          21 :     qof_object_foreach (GNC_ID_VENDOR,   book, billterm_scrub_vendor, ht);
     716                 :          21 :     qof_object_foreach (GNC_ID_BILLTERM, book, billterm_scrub_cb, &list);
     717                 :             : 
     718                 :             :     /* destroy the list of "grandchildren" bill terms */
     719                 :          21 :     for (node = list; node; node = node->next)
     720                 :             :     {
     721                 :             :         gchar termstr[GUID_ENCODING_LENGTH + 1];
     722                 :           0 :         term = static_cast<decltype (term)> (node->data);
     723                 :             : 
     724                 :           0 :         guid_to_string_buff (qof_instance_get_guid (QOF_INSTANCE (term)), termstr);
     725                 :           0 :         PWARN ("deleting grandchild billterm: %s\n", termstr);
     726                 :             : 
     727                 :             :         /* Make sure the parent has no children */
     728                 :           0 :         parent = gncBillTermGetParent (term);
     729                 :           0 :         gncBillTermSetChild (parent, NULL);
     730                 :             : 
     731                 :             :         /* Destroy this bill term */
     732                 :           0 :         gncBillTermBeginEdit (term);
     733                 :           0 :         gncBillTermDestroy (term);
     734                 :             :     }
     735                 :             : 
     736                 :             :     /* reset the refcounts as necessary */
     737                 :          21 :     g_hash_table_foreach (ht, billterm_reset_refcount, NULL);
     738                 :             : 
     739                 :          21 :     g_list_free (list);
     740                 :          21 :     g_hash_table_destroy (ht);
     741                 :          21 : }
     742                 :             : 
     743                 :             : static gboolean
     744                 :           4 : billterm_ns (FILE* out)
     745                 :             : {
     746                 :           4 :     g_return_val_if_fail (out, FALSE);
     747                 :             :     return
     748                 :           4 :         gnc_xml2_write_namespace_decl (out, "billterm")
     749                 :           4 :         && gnc_xml2_write_namespace_decl (out, "bt-days")
     750                 :           8 :         && gnc_xml2_write_namespace_decl (out, "bt-prox");
     751                 :             : }
     752                 :             : 
     753                 :             : void
     754                 :          61 : gnc_billterm_xml_initialize (void)
     755                 :             : {
     756                 :             :     static GncXmlDataType_t be_data =
     757                 :             :     {
     758                 :             :         GNC_FILE_BACKEND_VERS,
     759                 :             :         gnc_billterm_string,
     760                 :             :         billterm_sixtp_parser_create,
     761                 :             :         NULL,           /* add_item */
     762                 :             :         billterm_get_count,
     763                 :             :         billterm_write,
     764                 :             :         billterm_scrub,
     765                 :             :         billterm_ns,
     766                 :             :     };
     767                 :             : 
     768                 :          61 :     gnc_xml_register_backend(be_data);
     769                 :          61 : }
     770                 :             : 
     771                 :             : GncBillTerm*
     772                 :           0 : gnc_billterm_xml_find_or_create (QofBook* book, GncGUID* guid)
     773                 :             : {
     774                 :             :     GncBillTerm* term;
     775                 :             :     gchar guidstr[GUID_ENCODING_LENGTH + 1];
     776                 :             : 
     777                 :           0 :     guid_to_string_buff (guid, guidstr);
     778                 :           0 :     g_return_val_if_fail (book, NULL);
     779                 :           0 :     g_return_val_if_fail (guid, NULL);
     780                 :           0 :     term = gncBillTermLookup (book, guid);
     781                 :           0 :     DEBUG ("looking for billterm %s, found %p", guidstr, term);
     782                 :           0 :     if (!term)
     783                 :             :     {
     784                 :           0 :         term = gncBillTermCreate (book);
     785                 :           0 :         gncBillTermBeginEdit (term);
     786                 :           0 :         gncBillTermSetGUID (term, guid);
     787                 :           0 :         gncBillTermCommitEdit (term);
     788                 :           0 :         DEBUG ("Created term: %p", term);
     789                 :             :     }
     790                 :             :     else
     791                 :           0 :         gncBillTermDecRef (term);
     792                 :             : 
     793                 :           0 :     return term;
     794                 :             : }
        

Generated by: LCOV version 2.0-1