GnuCash 2.4.99
gnc-bill-term-sql.c
Go to the documentation of this file.
00001 /********************************************************************\
00002  * gnc-bill-term-sql.c -- billing term sql backend                  *
00003  *                                                                  *
00004  * This program is free software; you can redistribute it and/or    *
00005  * modify it under the terms of the GNU General Public License as   *
00006  * published by the Free Software Foundation; either version 2 of   *
00007  * the License, or (at your option) any later version.              *
00008  *                                                                  *
00009  * This program is distributed in the hope that it will be useful,  *
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00012  * GNU General Public License for more details.                     *
00013  *                                                                  *
00014  * You should have received a copy of the GNU General Public License*
00015  * along with this program; if not, contact:                        *
00016  *                                                                  *
00017  * Free Software Foundation           Voice:  +1-617-542-5942       *
00018  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00019  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00020  *                                                                  *
00021 \********************************************************************/
00022 
00031 #include "config.h"
00032 
00033 #include <glib.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 
00037 #include "gnc-backend-sql.h"
00038 #include "gnc-slots-sql.h"
00039 
00040 #include "gncBillTermP.h"
00041 #include "gncInvoice.h"
00042 #include "gnc-bill-term-sql.h"
00043 #include "qof.h"
00044 
00045 #define _GNC_MOD_NAME   GNC_ID_BILLTERM
00046 
00047 static QofLogModule log_module = G_LOG_DOMAIN;
00048 
00049 #define MAX_NAME_LEN 2048
00050 #define MAX_DESCRIPTION_LEN 2048
00051 #define MAX_TYPE_LEN 2048
00052 
00053 static void set_invisible( gpointer data, gboolean value );
00054 static gpointer bt_get_parent( gpointer data );
00055 static void bt_set_parent( gpointer data, gpointer value );
00056 static void bt_set_parent_guid( gpointer data, gpointer value );
00057 
00058 #define TABLE_NAME "billterms"
00059 #define TABLE_VERSION 2
00060 
00061 static GncSqlColumnTableEntry col_table[] =
00062 {
00063     { "guid",         CT_GUID,        0,                   COL_NNUL | COL_PKEY, "guid" },
00064     { "name",         CT_STRING,      MAX_NAME_LEN,        COL_NNUL,          "name" },
00065     { "description",  CT_STRING,      MAX_DESCRIPTION_LEN, COL_NNUL,          NULL, GNC_BILLTERM_DESC },
00066     {
00067         "refcount",     CT_INT,         0,                   COL_NNUL,          NULL, NULL,
00068         (QofAccessFunc)gncBillTermGetRefcount,  (QofSetterFunc)gncBillTermSetRefcount
00069     },
00070     {
00071         "invisible",    CT_BOOLEAN,     0,                   COL_NNUL,          NULL, NULL,
00072         (QofAccessFunc)gncBillTermGetInvisible, (QofSetterFunc)set_invisible
00073     },
00074     {
00075         "parent",       CT_GUID,       0,                   0,                 NULL, NULL,
00076         (QofAccessFunc)bt_get_parent,    (QofSetterFunc)bt_set_parent
00077     },
00078 #if 0
00079     {
00080         "child",        CT_BILLTERMREF, 0,                   0,                 NULL, NULL,
00081         (QofAccessFunc)gncBillTermReturnChild,  (QofSetterFunc)gncBillTermSetChild
00082     },
00083 #endif
00084     { "type",         CT_STRING,      MAX_TYPE_LEN,        COL_NNUL,          NULL, GNC_BILLTERM_TYPE },
00085     { "duedays",      CT_INT,         0,                   0,                 0,    GNC_BILLTERM_DUEDAYS },
00086     { "discountdays", CT_INT,         0,                   0,                 0,    GNC_BILLTERM_DISCDAYS },
00087     { "discount",     CT_NUMERIC,     0,                   0,                 0,    GNC_BILLTERM_DISCOUNT },
00088     { "cutoff",       CT_INT,         0,                   0,                 0,    GNC_BILLTERM_CUTOFF },
00089     { NULL }
00090 };
00091 
00092 static GncSqlColumnTableEntry billterm_parent_col_table[] =
00093 {
00094     { "parent", CT_GUID, 0, 0, NULL, NULL, NULL, (QofSetterFunc)bt_set_parent_guid },
00095     { NULL }
00096 };
00097 
00098 typedef struct
00099 {
00100     /*@ dependent @*/ GncBillTerm* billterm;
00101     GncGUID guid;
00102     gboolean have_guid;
00103 } billterm_parent_guid_struct;
00104 
00105 static void
00106 set_invisible( gpointer data, gboolean value )
00107 {
00108     GncBillTerm* term = GNC_BILLTERM(data);
00109 
00110     g_return_if_fail( term != NULL );
00111 
00112     if ( value )
00113     {
00114         gncBillTermMakeInvisible( term );
00115     }
00116 }
00117 
00118 static /*@ null @*//*@ dependent @*/ gpointer
00119 bt_get_parent( gpointer pObject )
00120 {
00121     const GncBillTerm* billterm;
00122     const GncBillTerm* pParent;
00123     const GncGUID* parent_guid;
00124 
00125     g_return_val_if_fail( pObject != NULL, NULL );
00126     g_return_val_if_fail( GNC_IS_BILLTERM(pObject), NULL );
00127 
00128     billterm = GNC_BILLTERM(pObject);
00129     pParent = gncBillTermGetParent( billterm );
00130     if ( pParent == NULL )
00131     {
00132         parent_guid = NULL;
00133     }
00134     else
00135     {
00136         parent_guid = qof_instance_get_guid( QOF_INSTANCE(pParent) );
00137     }
00138 
00139     return (gpointer)parent_guid;
00140 }
00141 
00142 static void
00143 bt_set_parent( gpointer data, gpointer value )
00144 {
00145     GncBillTerm* billterm;
00146     GncBillTerm* parent;
00147     QofBook* pBook;
00148     GncGUID* guid = (GncGUID*)value;
00149 
00150     g_return_if_fail( data != NULL );
00151     g_return_if_fail( GNC_IS_BILLTERM(data) );
00152 
00153     billterm = GNC_BILLTERM(data);
00154     pBook = qof_instance_get_book( QOF_INSTANCE(billterm) );
00155     if ( guid != NULL )
00156     {
00157         parent = gncBillTermLookup( pBook, guid );
00158         if ( parent != NULL )
00159         {
00160             gncBillTermSetParent( billterm, parent );
00161             gncBillTermSetChild( parent, billterm );
00162         }
00163     }
00164 }
00165 
00166 static void
00167 bt_set_parent_guid( gpointer pObject, /*@ null @*/ gpointer pValue )
00168 {
00169     billterm_parent_guid_struct* s = (billterm_parent_guid_struct*)pObject;
00170     GncGUID* guid = (GncGUID*)pValue;
00171 
00172     g_return_if_fail( pObject != NULL );
00173     g_return_if_fail( pValue != NULL );
00174 
00175     s->guid = *guid;
00176     s->have_guid = TRUE;
00177 }
00178 
00179 static GncBillTerm*
00180 load_single_billterm( GncSqlBackend* be, GncSqlRow* row,
00181                       GList** l_billterms_needing_parents )
00182 {
00183     const GncGUID* guid;
00184     GncBillTerm* pBillTerm;
00185 
00186     g_return_val_if_fail( be != NULL, NULL );
00187     g_return_val_if_fail( row != NULL, NULL );
00188 
00189     guid = gnc_sql_load_guid( be, row );
00190     pBillTerm = gncBillTermLookup( be->book, guid );
00191     if ( pBillTerm == NULL )
00192     {
00193         pBillTerm = gncBillTermCreate( be->book );
00194     }
00195     gnc_sql_load_object( be, row, GNC_ID_BILLTERM, pBillTerm, col_table );
00196 
00197     /* If the billterm doesn't have a parent, it might be because it hasn't been loaded yet.
00198        If so, add this billterm to the list of billterms with no parent, along with the parent
00199        GncGUID so that after they are all loaded, the parents can be fixed up. */
00200     if ( gncBillTermGetParent( pBillTerm ) == NULL )
00201     {
00202         billterm_parent_guid_struct* s = g_malloc( (gsize)sizeof(billterm_parent_guid_struct) );
00203         g_assert( s != NULL );
00204 
00205         s->billterm = pBillTerm;
00206         s->have_guid = FALSE;
00207         gnc_sql_load_object( be, row, GNC_ID_TAXTABLE, s, billterm_parent_col_table );
00208         if ( s->have_guid )
00209         {
00210             *l_billterms_needing_parents = g_list_prepend( *l_billterms_needing_parents, s );
00211         }
00212         else
00213         {
00214             g_free( s );
00215         }
00216     }
00217 
00218     qof_instance_mark_clean( QOF_INSTANCE(pBillTerm) );
00219 
00220     return pBillTerm;
00221 }
00222 
00223 static void
00224 load_all_billterms( GncSqlBackend* be )
00225 {
00226     GncSqlStatement* stmt;
00227     GncSqlResult* result;
00228     QofBook* pBook;
00229 
00230     g_return_if_fail( be != NULL );
00231 
00232     pBook = be->book;
00233 
00234     stmt = gnc_sql_create_select_statement( be, TABLE_NAME );
00235     result = gnc_sql_execute_select_statement( be, stmt );
00236     gnc_sql_statement_dispose( stmt );
00237     if ( result != NULL )
00238     {
00239         GncSqlRow* row;
00240         GList* list = NULL;
00241         GList* l_billterms_needing_parents = NULL;
00242 
00243         row = gnc_sql_result_get_first_row( result );
00244         while ( row != NULL )
00245         {
00246             GncBillTerm* pBillTerm = load_single_billterm( be, row, &l_billterms_needing_parents );
00247             if ( pBillTerm != NULL )
00248             {
00249                 list = g_list_append( list, pBillTerm );
00250             }
00251             row = gnc_sql_result_get_next_row( result );
00252         }
00253         gnc_sql_result_dispose( result );
00254 
00255         if ( list != NULL )
00256         {
00257             gnc_sql_slots_load_for_list( be, list );
00258             g_list_free( list );
00259         }
00260 
00261         /* While there are items on the list of billterms needing parents,
00262            try to see if the parent has now been loaded.  Theory says that if
00263            items are removed from the front and added to the back if the
00264            parent is still not available, then eventually, the list will
00265            shrink to size 0. */
00266         if ( l_billterms_needing_parents != NULL )
00267         {
00268             gboolean progress_made = TRUE;
00269             GncTaxTable* root;
00270             Account* pParent;
00271             GList* elem;
00272 
00273             while ( progress_made )
00274             {
00275                 progress_made = FALSE;
00276                 for ( elem = l_billterms_needing_parents; elem != NULL; elem = g_list_next( elem ) )
00277                 {
00278                     billterm_parent_guid_struct* s = (billterm_parent_guid_struct*)elem->data;
00279                     bt_set_parent( s->billterm, &s->guid );
00280                     l_billterms_needing_parents = g_list_delete_link( l_billterms_needing_parents, elem );
00281                     progress_made = TRUE;
00282                 }
00283             }
00284         }
00285     }
00286 }
00287 
00288 /* ================================================================= */
00289 typedef struct
00290 {
00291     GncSqlBackend* be;
00292     gboolean is_ok;
00293 } write_billterms_t;
00294 
00295 static void
00296 do_save_billterm( QofInstance* inst, gpointer p2 )
00297 {
00298     write_billterms_t* data = (write_billterms_t*)p2;
00299 
00300     if ( data->is_ok )
00301     {
00302         data->is_ok = gnc_sql_save_billterm( data->be, inst );
00303     }
00304 }
00305 
00306 static gboolean
00307 write_billterms( GncSqlBackend* be )
00308 {
00309     write_billterms_t data;
00310 
00311     g_return_val_if_fail( be != NULL, FALSE );
00312 
00313     data.be = be;
00314     data.is_ok = TRUE;
00315     qof_object_foreach( GNC_ID_BILLTERM, be->book, do_save_billterm, &data );
00316     return data.is_ok;
00317 }
00318 
00319 /* ================================================================= */
00320 static void
00321 create_billterm_tables( GncSqlBackend* be )
00322 {
00323     gint version;
00324 
00325     g_return_if_fail( be != NULL );
00326 
00327     version = gnc_sql_get_table_version( be, TABLE_NAME );
00328     if ( version == 0 )
00329     {
00330         gnc_sql_create_table( be, TABLE_NAME, TABLE_VERSION, col_table );
00331     }
00332     else if ( version == 1 )
00333     {
00334         /* Upgrade 64 bit int handling */
00335         gnc_sql_upgrade_table( be, TABLE_NAME, col_table );
00336         gnc_sql_set_table_version( be, TABLE_NAME, TABLE_VERSION );
00337 
00338         PINFO("Billterms table upgraded from version 1 to version %d\n", TABLE_VERSION);
00339     }
00340 }
00341 
00342 /* ================================================================= */
00343 gboolean
00344 gnc_sql_save_billterm( GncSqlBackend* be, QofInstance* inst )
00345 {
00346     g_return_val_if_fail( inst != NULL, FALSE );
00347     g_return_val_if_fail( GNC_IS_BILLTERM(inst), FALSE );
00348     g_return_val_if_fail( be != NULL, FALSE );
00349 
00350     return gnc_sql_commit_standard_item( be, inst, TABLE_NAME, GNC_ID_BILLTERM, col_table );
00351 }
00352 
00353 /* ================================================================= */
00354 static void
00355 load_billterm_guid( const GncSqlBackend* be, GncSqlRow* row,
00356                     QofSetterFunc setter, gpointer pObject,
00357                     const GncSqlColumnTableEntry* table_row )
00358 {
00359     const GValue* val;
00360     GncGUID guid;
00361     GncBillTerm* term = NULL;
00362 
00363     g_return_if_fail( be != NULL );
00364     g_return_if_fail( row != NULL );
00365     g_return_if_fail( pObject != NULL );
00366     g_return_if_fail( table_row != NULL );
00367 
00368     val = gnc_sql_row_get_value_at_col_name( row, table_row->col_name );
00369     if ( val != NULL && G_VALUE_HOLDS_STRING( val ) && g_value_get_string( val ) != NULL )
00370     {
00371         string_to_guid( g_value_get_string( val ), &guid );
00372         term = gncBillTermLookup( be->book, &guid );
00373         if ( term != NULL )
00374         {
00375             if ( table_row->gobj_param_name != NULL )
00376             {
00377                 g_object_set( pObject, table_row->gobj_param_name, term, NULL );
00378             }
00379             else
00380             {
00381                 (*setter)( pObject, (const gpointer)term );
00382             }
00383         }
00384         else
00385         {
00386             PWARN( "Billterm ref '%s' not found", g_value_get_string( val ) );
00387         }
00388     }
00389 }
00390 
00391 static GncSqlColumnTypeHandler billterm_guid_handler
00392 = { load_billterm_guid,
00393     gnc_sql_add_objectref_guid_col_info_to_list,
00394     gnc_sql_add_colname_to_list,
00395     gnc_sql_add_gvalue_objectref_guid_to_slist
00396   };
00397 /* ================================================================= */
00398 void
00399 gnc_billterm_sql_initialize( void )
00400 {
00401     static GncSqlObjectBackend be_data =
00402     {
00403         GNC_SQL_BACKEND_VERSION,
00404         GNC_ID_BILLTERM,
00405         gnc_sql_save_billterm,                          /* commit */
00406         load_all_billterms,                                     /* initial_load */
00407         create_billterm_tables,                         /* create_tables */
00408         NULL, NULL, NULL,
00409         write_billterms                                         /* write */
00410     };
00411 
00412     qof_object_register_backend( GNC_ID_BILLTERM, GNC_SQL_BACKEND, &be_data );
00413 
00414     gnc_sql_register_col_type_handler( CT_BILLTERMREF, &billterm_guid_handler );
00415 }
00416 /* ========================== END OF FILE ===================== */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines