GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnc-bill-term-sql.c
Go to the documentation of this file.
1 /********************************************************************\
2  * gnc-bill-term-sql.c -- billing term sql backend *
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 [email protected] *
20  * *
21 \********************************************************************/
22 
31 #include "config.h"
32 
33 #include <glib.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 #include "gnc-backend-sql.h"
38 #include "gnc-slots-sql.h"
39 
40 #include "gncBillTermP.h"
41 #include "gncInvoice.h"
42 #include "gnc-bill-term-sql.h"
43 #include "qof.h"
44 
45 #define _GNC_MOD_NAME GNC_ID_BILLTERM
46 
47 static QofLogModule log_module = G_LOG_DOMAIN;
48 
49 #define MAX_NAME_LEN 2048
50 #define MAX_DESCRIPTION_LEN 2048
51 #define MAX_TYPE_LEN 2048
52 
53 static void set_invisible( gpointer data, gboolean value );
54 static gpointer bt_get_parent( gpointer data );
55 static void bt_set_parent( gpointer data, gpointer value );
56 static void bt_set_parent_guid( gpointer data, gpointer value );
57 
58 #define TABLE_NAME "billterms"
59 #define TABLE_VERSION 2
60 
61 static GncSqlColumnTableEntry col_table[] =
62 {
63  { "guid", CT_GUID, 0, COL_NNUL | COL_PKEY, "guid" },
64  { "name", CT_STRING, MAX_NAME_LEN, COL_NNUL, "name" },
65  { "description", CT_STRING, MAX_DESCRIPTION_LEN, COL_NNUL, NULL, GNC_BILLTERM_DESC },
66  {
67  "refcount", CT_INT, 0, COL_NNUL, NULL, NULL,
68  (QofAccessFunc)gncBillTermGetRefcount, (QofSetterFunc)gncBillTermSetRefcount
69  },
70  {
71  "invisible", CT_BOOLEAN, 0, COL_NNUL, NULL, NULL,
72  (QofAccessFunc)gncBillTermGetInvisible, (QofSetterFunc)set_invisible
73  },
74  {
75  "parent", CT_GUID, 0, 0, NULL, NULL,
76  (QofAccessFunc)bt_get_parent, (QofSetterFunc)bt_set_parent
77  },
78  { "type", CT_STRING, MAX_TYPE_LEN, COL_NNUL, NULL, GNC_BILLTERM_TYPE },
79  { "duedays", CT_INT, 0, 0, 0, GNC_BILLTERM_DUEDAYS },
80  { "discountdays", CT_INT, 0, 0, 0, GNC_BILLTERM_DISCDAYS },
81  { "discount", CT_NUMERIC, 0, 0, 0, GNC_BILLTERM_DISCOUNT },
82  { "cutoff", CT_INT, 0, 0, 0, GNC_BILLTERM_CUTOFF },
83  { NULL }
84 };
85 
86 static GncSqlColumnTableEntry billterm_parent_col_table[] =
87 {
88  { "parent", CT_GUID, 0, 0, NULL, NULL, NULL, (QofSetterFunc)bt_set_parent_guid },
89  { NULL }
90 };
91 
92 typedef struct
93 {
94  /*@ dependent @*/ GncBillTerm* billterm;
95  GncGUID guid;
96  gboolean have_guid;
98 
99 static void
100 set_invisible( gpointer data, gboolean value )
101 {
102  GncBillTerm* term = GNC_BILLTERM(data);
103 
104  g_return_if_fail( term != NULL );
105 
106  if ( value )
107  {
108  gncBillTermMakeInvisible( term );
109  }
110 }
111 
112 static /*@ null @*//*@ dependent @*/ gpointer
113 bt_get_parent( gpointer pObject )
114 {
115  const GncBillTerm* billterm;
116  const GncBillTerm* pParent;
117  const GncGUID* parent_guid;
118 
119  g_return_val_if_fail( pObject != NULL, NULL );
120  g_return_val_if_fail( GNC_IS_BILLTERM(pObject), NULL );
121 
122  billterm = GNC_BILLTERM(pObject);
123  pParent = gncBillTermGetParent( billterm );
124  if ( pParent == NULL )
125  {
126  parent_guid = NULL;
127  }
128  else
129  {
130  parent_guid = qof_instance_get_guid( QOF_INSTANCE(pParent) );
131  }
132 
133  return (gpointer)parent_guid;
134 }
135 
136 static void
137 bt_set_parent( gpointer data, gpointer value )
138 {
139  GncBillTerm* billterm;
140  GncBillTerm* parent;
141  QofBook* pBook;
142  GncGUID* guid = (GncGUID*)value;
143 
144  g_return_if_fail( data != NULL );
145  g_return_if_fail( GNC_IS_BILLTERM(data) );
146 
147  billterm = GNC_BILLTERM(data);
148  pBook = qof_instance_get_book( QOF_INSTANCE(billterm) );
149  if ( guid != NULL )
150  {
151  parent = gncBillTermLookup( pBook, guid );
152  if ( parent != NULL )
153  {
154  gncBillTermSetParent( billterm, parent );
155  gncBillTermSetChild( parent, billterm );
156  }
157  }
158 }
159 
160 static void
161 bt_set_parent_guid( gpointer pObject, /*@ null @*/ gpointer pValue )
162 {
164  GncGUID* guid = (GncGUID*)pValue;
165 
166  g_return_if_fail( pObject != NULL );
167  g_return_if_fail( pValue != NULL );
168 
169  s->guid = *guid;
170  s->have_guid = TRUE;
171 }
172 
173 static GncBillTerm*
174 load_single_billterm( GncSqlBackend* be, GncSqlRow* row,
175  GList** l_billterms_needing_parents )
176 {
177  const GncGUID* guid;
178  GncBillTerm* pBillTerm;
179 
180  g_return_val_if_fail( be != NULL, NULL );
181  g_return_val_if_fail( row != NULL, NULL );
182 
183  guid = gnc_sql_load_guid( be, row );
184  pBillTerm = gncBillTermLookup( be->book, guid );
185  if ( pBillTerm == NULL )
186  {
187  pBillTerm = gncBillTermCreate( be->book );
188  }
189  gnc_sql_load_object( be, row, GNC_ID_BILLTERM, pBillTerm, col_table );
190 
191  /* If the billterm doesn't have a parent, it might be because it hasn't been loaded yet.
192  If so, add this billterm to the list of billterms with no parent, along with the parent
193  GncGUID so that after they are all loaded, the parents can be fixed up. */
194  if ( gncBillTermGetParent( pBillTerm ) == NULL )
195  {
196  billterm_parent_guid_struct* s = g_malloc( (gsize)sizeof(billterm_parent_guid_struct) );
197  g_assert( s != NULL );
198 
199  s->billterm = pBillTerm;
200  s->have_guid = FALSE;
201  gnc_sql_load_object( be, row, GNC_ID_TAXTABLE, s, billterm_parent_col_table );
202  if ( s->have_guid )
203  {
204  *l_billterms_needing_parents = g_list_prepend( *l_billterms_needing_parents, s );
205  }
206  else
207  {
208  g_free( s );
209  }
210  }
211 
212  qof_instance_mark_clean( QOF_INSTANCE(pBillTerm) );
213 
214  return pBillTerm;
215 }
216 
217 static void
218 load_all_billterms( GncSqlBackend* be )
219 {
220  GncSqlStatement* stmt;
221  GncSqlResult* result;
222 
223  g_return_if_fail( be != NULL );
224 
225  stmt = gnc_sql_create_select_statement( be, TABLE_NAME );
226  result = gnc_sql_execute_select_statement( be, stmt );
227  gnc_sql_statement_dispose( stmt );
228  if ( result != NULL )
229  {
230  GncSqlRow* row;
231  GList* list = NULL;
232  GList* l_billterms_needing_parents = NULL;
233 
234  row = gnc_sql_result_get_first_row( result );
235  while ( row != NULL )
236  {
237  GncBillTerm* pBillTerm = load_single_billterm( be, row, &l_billterms_needing_parents );
238  if ( pBillTerm != NULL )
239  {
240  list = g_list_append( list, pBillTerm );
241  }
242  row = gnc_sql_result_get_next_row( result );
243  }
244  gnc_sql_result_dispose( result );
245 
246  if ( list != NULL )
247  {
248  gnc_sql_slots_load_for_list( be, list );
249  g_list_free( list );
250  }
251 
252  /* While there are items on the list of billterms needing parents,
253  try to see if the parent has now been loaded. Theory says that if
254  items are removed from the front and added to the back if the
255  parent is still not available, then eventually, the list will
256  shrink to size 0. */
257  if ( l_billterms_needing_parents != NULL )
258  {
259  gboolean progress_made = TRUE;
260  GList* elem;
261 
262  while ( progress_made )
263  {
264  progress_made = FALSE;
265  for ( elem = l_billterms_needing_parents; elem != NULL; elem = g_list_next( elem ) )
266  {
268  bt_set_parent( s->billterm, &s->guid );
269  l_billterms_needing_parents = g_list_delete_link( l_billterms_needing_parents, elem );
270  progress_made = TRUE;
271  }
272  }
273  }
274  }
275 }
276 
277 /* ================================================================= */
278 typedef struct
279 {
280  GncSqlBackend* be;
281  gboolean is_ok;
283 
284 static void
285 do_save_billterm( QofInstance* inst, gpointer p2 )
286 {
288 
289  if ( data->is_ok )
290  {
291  data->is_ok = gnc_sql_save_billterm( data->be, inst );
292  }
293 }
294 
295 static gboolean
296 write_billterms( GncSqlBackend* be )
297 {
298  write_billterms_t data;
299 
300  g_return_val_if_fail( be != NULL, FALSE );
301 
302  data.be = be;
303  data.is_ok = TRUE;
304  qof_object_foreach( GNC_ID_BILLTERM, be->book, do_save_billterm, &data );
305  return data.is_ok;
306 }
307 
308 /* ================================================================= */
309 static void
310 create_billterm_tables( GncSqlBackend* be )
311 {
312  gint version;
313 
314  g_return_if_fail( be != NULL );
315 
316  version = gnc_sql_get_table_version( be, TABLE_NAME );
317  if ( version == 0 )
318  {
319  gnc_sql_create_table( be, TABLE_NAME, TABLE_VERSION, col_table );
320  }
321  else if ( version == 1 )
322  {
323  /* Upgrade 64 bit int handling */
324  gnc_sql_upgrade_table( be, TABLE_NAME, col_table );
325  gnc_sql_set_table_version( be, TABLE_NAME, TABLE_VERSION );
326 
327  PINFO("Billterms table upgraded from version 1 to version %d\n", TABLE_VERSION);
328  }
329 }
330 
331 /* ================================================================= */
332 gboolean
333 gnc_sql_save_billterm( GncSqlBackend* be, QofInstance* inst )
334 {
335  g_return_val_if_fail( inst != NULL, FALSE );
336  g_return_val_if_fail( GNC_IS_BILLTERM(inst), FALSE );
337  g_return_val_if_fail( be != NULL, FALSE );
338 
339  return gnc_sql_commit_standard_item( be, inst, TABLE_NAME, GNC_ID_BILLTERM, col_table );
340 }
341 
342 /* ================================================================= */
343 static void
344 load_billterm_guid( const GncSqlBackend* be, GncSqlRow* row,
345  QofSetterFunc setter, gpointer pObject,
346  const GncSqlColumnTableEntry* table_row )
347 {
348  const GValue* val;
349  GncGUID guid;
350  GncBillTerm* term = NULL;
351 
352  g_return_if_fail( be != NULL );
353  g_return_if_fail( row != NULL );
354  g_return_if_fail( pObject != NULL );
355  g_return_if_fail( table_row != NULL );
356 
357  val = gnc_sql_row_get_value_at_col_name( row, table_row->col_name );
358  if ( val != NULL && G_VALUE_HOLDS_STRING( val ) && g_value_get_string( val ) != NULL )
359  {
360  string_to_guid( g_value_get_string( val ), &guid );
361  term = gncBillTermLookup( be->book, &guid );
362  if ( term != NULL )
363  {
364  if ( table_row->gobj_param_name != NULL )
365  {
366  qof_instance_increase_editlevel (pObject);
367  g_object_set( pObject, table_row->gobj_param_name, term, NULL );
368  qof_instance_decrease_editlevel (pObject);
369  }
370  else
371  {
372  (*setter)( pObject, (const gpointer)term );
373  }
374  }
375  else
376  {
377  PWARN( "Billterm ref '%s' not found", g_value_get_string( val ) );
378  }
379  }
380 }
381 
382 static GncSqlColumnTypeHandler billterm_guid_handler
383 = { load_billterm_guid,
387  };
388 /* ================================================================= */
389 void
390 gnc_billterm_sql_initialize( void )
391 {
392  static GncSqlObjectBackend be_data =
393  {
394  GNC_SQL_BACKEND_VERSION,
395  GNC_ID_BILLTERM,
396  gnc_sql_save_billterm, /* commit */
397  load_all_billterms, /* initial_load */
398  create_billterm_tables, /* create_tables */
399  NULL, NULL, NULL,
400  write_billterms /* write */
401  };
402 
403  qof_object_register_backend( GNC_ID_BILLTERM, GNC_SQL_BACKEND, &be_data );
404 
405  gnc_sql_register_col_type_handler( CT_BILLTERMREF, &billterm_guid_handler );
406 }
407 /* ========================== END OF FILE ===================== */
gboolean qof_object_register_backend(QofIdTypeConst type_name, const char *backend_name, gpointer be_data)
const GncGUID * qof_instance_get_guid(gconstpointer)
gint gnc_sql_get_table_version(const GncSqlBackend *be, const gchar *table_name)
QofBook * qof_instance_get_book(gconstpointer)
void gnc_sql_upgrade_table(GncSqlBackend *be, const gchar *table_name, const GncSqlColumnTableEntry *col_table)
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
#define PINFO(format, args...)
Definition: qoflog.h:249
void gnc_sql_add_colname_to_list(const GncSqlColumnTableEntry *table_row, GList **pList)
load and save accounts data to SQL
GncSqlStatement * gnc_sql_create_select_statement(GncSqlBackend *be, const gchar *table_name)
#define COL_NNUL
gboolean string_to_guid(const gchar *string, GncGUID *guid)
gboolean gnc_sql_create_table(GncSqlBackend *be, const gchar *table_name, gint table_version, const GncSqlColumnTableEntry *col_table)
load and save data to SQL
void gnc_sql_register_col_type_handler(const gchar *colType, const GncSqlColumnTypeHandler *handler)
void gnc_sql_add_objectref_guid_col_info_to_list(const GncSqlBackend *be, const GncSqlColumnTableEntry *table_row, GList **pList)
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
Definition: qofclass.h:177
load and save accounts data to SQL
QofBook * book
Definition: guid.h:65
#define COL_PKEY
#define PWARN(format, args...)
Definition: qoflog.h:243
const GncGUID * gnc_sql_load_guid(const GncSqlBackend *be, GncSqlRow *row)
gboolean gnc_sql_set_table_version(GncSqlBackend *be, const gchar *table_name, gint version)
void gnc_sql_add_gvalue_objectref_guid_to_slist(const GncSqlBackend *be, QofIdTypeConst obj_name, const gpointer pObject, const GncSqlColumnTableEntry *table_row, GSList **pList)
void gnc_sql_slots_load_for_list(GncSqlBackend *be, GList *list)
void qof_object_foreach(QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
GncSqlResult * gnc_sql_execute_select_statement(GncSqlBackend *be, GncSqlStatement *stmt)
void gnc_sql_load_object(const GncSqlBackend *be, GncSqlRow *row, QofIdTypeConst obj_name, gpointer pObject, const GncSqlColumnTableEntry *table)
const gchar * gobj_param_name
Business Invoice Interface.
gboolean gnc_sql_commit_standard_item(GncSqlBackend *be, QofInstance *inst, const gchar *tableName, QofIdTypeConst obj_name, const GncSqlColumnTableEntry *col_table)
void(* QofSetterFunc)(gpointer, gpointer)
Definition: qofclass.h:184
const gchar * QofLogModule
Definition: qofid.h:89