|
GnuCash 2.4.99
|
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 ===================== */
1.7.4