GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnc-budget.c
1 /********************************************************************\
2  * gnc-budget.c -- Implementation of the top level Budgeting API. *
3  * Copyright (C) 04 sep 2003 Darin Willits <[email protected]> *
4  * Copyright (C) 2005-2006 Chris Shoemaker <[email protected]> *
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 [email protected] *
22  * *
23 \********************************************************************/
24 
25 #include <config.h>
26 #include <glib.h>
27 #include <glib/gprintf.h>
28 #include <glib/gi18n.h>
29 #include <time.h>
30 #include <qof.h>
31 #include <qofbookslots.h>
32 #include <gnc-gdate-utils.h>
33 #include <qofinstance-p.h>
34 
35 #include "Account.h"
36 
37 #include "gnc-budget.h"
38 #include "gnc-commodity.h"
39 
40 static QofLogModule log_module = GNC_MOD_ENGINE;
41 
42 enum
43 {
44  PROP_0,
45  PROP_NAME, /* Table */
46  PROP_DESCRIPTION, /* Table */
47  PROP_NUM_PERIODS, /* Table */
48  PROP_RUNTIME_0,
49  PROP_RECURRENCE, /* Cached pointer; Recurrence table holds budget guid */
50 };
51 
52 struct budget_s
53 {
54  QofInstance inst;
55 };
56 
57 typedef struct
58 {
59  QofInstanceClass parent_class;
60 } BudgetClass;
61 
62 typedef struct BudgetPrivate
63 {
64  /* The name is an arbitrary string assigned by the user. */
65  gchar* name;
66 
67  /* The description is an arbitrary string assigned by the user. */
68  gchar* description;
69 
70  /* Recurrence (period info) for the budget */
71  Recurrence recurrence;
72 
73  /* Number of periods */
74  guint num_periods;
76 
77 #define GET_PRIVATE(o) \
78  (G_TYPE_INSTANCE_GET_PRIVATE((o), GNC_TYPE_BUDGET, BudgetPrivate))
79 
81 {
82  QofInstanceClass parent_class;
83 };
84 
85 /* GObject Initialization */
86 G_DEFINE_TYPE(GncBudget, gnc_budget, QOF_TYPE_INSTANCE)
87 
88 static void
89 gnc_budget_init(GncBudget* budget)
90 {
91  BudgetPrivate* priv;
92  GDate date;
93 
94  priv = GET_PRIVATE(budget);
95  priv->name = CACHE_INSERT(_("Unnamed Budget"));
96  priv->description = CACHE_INSERT("");
97 
98  priv->num_periods = 12;
99  gnc_gdate_set_today (&date);
100  g_date_subtract_days(&date, g_date_get_day(&date) - 1);
101  recurrenceSet(&priv->recurrence, 1, PERIOD_MONTH, &date, WEEKEND_ADJ_NONE);
102 }
103 
104 static void
105 gnc_budget_dispose (GObject *budgetp)
106 {
107  G_OBJECT_CLASS(gnc_budget_parent_class)->dispose(budgetp);
108 }
109 
110 static void
111 gnc_budget_finalize(GObject* budgetp)
112 {
113  G_OBJECT_CLASS(gnc_budget_parent_class)->finalize(budgetp);
114 }
115 
116 static void
117 gnc_budget_get_property( GObject* object,
118  guint prop_id,
119  GValue* value,
120  GParamSpec* pspec)
121 {
122  GncBudget* budget;
123  BudgetPrivate* priv;
124 
125  g_return_if_fail(GNC_IS_BUDGET(object));
126 
127  budget = GNC_BUDGET(object);
128  priv = GET_PRIVATE(budget);
129  switch ( prop_id )
130  {
131  case PROP_NAME:
132  g_value_set_string(value, priv->name);
133  break;
134  case PROP_DESCRIPTION:
135  g_value_set_string(value, priv->description);
136  break;
137  case PROP_NUM_PERIODS:
138  g_value_set_uint(value, priv->num_periods);
139  break;
140  case PROP_RECURRENCE:
141  /* TODO: Make this a BOXED type */
142  g_value_set_pointer(value, &priv->recurrence);
143  break;
144  default:
145  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
146  break;
147  }
148 }
149 
150 static void
151 gnc_budget_set_property( GObject* object,
152  guint prop_id,
153  const GValue* value,
154  GParamSpec* pspec)
155 {
156  GncBudget* budget;
157 
158  g_return_if_fail(GNC_IS_BUDGET(object));
159 
160  budget = GNC_BUDGET(object);
161  if (prop_id < PROP_RUNTIME_0)
162  g_assert (qof_instance_get_editlevel(budget));
163 
164  switch ( prop_id )
165  {
166  case PROP_NAME:
167  gnc_budget_set_name(budget, g_value_get_string(value));
168  break;
169  case PROP_DESCRIPTION:
170  gnc_budget_set_description(budget, g_value_get_string(value));
171  break;
172  case PROP_NUM_PERIODS:
173  gnc_budget_set_num_periods(budget, g_value_get_uint(value));
174  break;
175  case PROP_RECURRENCE:
176  gnc_budget_set_recurrence(budget, g_value_get_pointer(value));
177  break;
178  default:
179  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
180  break;
181  }
182 }
183 
184 static void
185 gnc_budget_class_init(GncBudgetClass* klass)
186 {
187  GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
188 
189  gobject_class->dispose = gnc_budget_dispose;
190  gobject_class->finalize = gnc_budget_finalize;
191  gobject_class->get_property = gnc_budget_get_property;
192  gobject_class->set_property = gnc_budget_set_property;
193 
194  g_type_class_add_private(klass, sizeof(BudgetPrivate));
195 
196  g_object_class_install_property(
197  gobject_class,
198  PROP_NAME,
199  g_param_spec_string( "name",
200  "Budget Name",
201  "The name is an arbitrary string "
202  "assigned by the user. It is intended "
203  "to be a short, 5 to 30 character long string "
204  "that is displayed by the GUI as the "
205  "budget mnemonic",
206  NULL,
207  G_PARAM_READWRITE));
208 
209  g_object_class_install_property(
210  gobject_class,
211  PROP_DESCRIPTION,
212  g_param_spec_string( "description",
213  "Budget Description",
214  "The description is an arbitrary string "
215  "assigned by the user. It is intended "
216  "to be a longer, 1-5 sentence description of "
217  "what the budget is all about.",
218  NULL,
219  G_PARAM_READWRITE));
220 
221  g_object_class_install_property(
222  gobject_class,
223  PROP_NUM_PERIODS,
224  g_param_spec_uint( "num-periods",
225  "Number of Periods",
226  "The number of periods for this budget.",
227  0,
228  G_MAXUINT32,
229  12,
230  G_PARAM_READWRITE));
231 
232  g_object_class_install_property(
233  gobject_class,
234  PROP_RECURRENCE,
235  g_param_spec_pointer( "recurrence",
236  "Budget Recurrence",
237  "about.",
238  G_PARAM_READWRITE));
239 }
240 
241 static void commit_err (QofInstance *inst, QofBackendError errcode)
242 {
243  PERR ("Failed to commit: %d", errcode);
244  gnc_engine_signal_commit_error( errcode );
245 }
246 
247 static void
248 gnc_budget_free(QofInstance *inst)
249 {
250  GncBudget *budget;
251  BudgetPrivate* priv;
252 
253  if (inst == NULL)
254  return;
255  g_return_if_fail(GNC_IS_BUDGET(inst));
256 
257  budget = GNC_BUDGET(inst);
258  priv = GET_PRIVATE(budget);
259 
260  /* We first send the message that this object is about to be
261  * destroyed so that any GUI elements can remove it before it is
262  * actually gone. */
263  qof_event_gen( &budget->inst, QOF_EVENT_DESTROY, NULL);
264 
265  CACHE_REMOVE(priv->name);
266  CACHE_REMOVE(priv->description);
267 
268  /* qof_instance_release (&budget->inst); */
269  g_object_unref(budget);
270 }
271 
272 static void noop (QofInstance *inst) {}
273 
274 void
275 gnc_budget_begin_edit(GncBudget *bgt)
276 {
277  qof_begin_edit(QOF_INSTANCE(bgt));
278 }
279 
280 void
281 gnc_budget_commit_edit(GncBudget *bgt)
282 {
283  if (!qof_commit_edit(QOF_INSTANCE(bgt))) return;
284  qof_commit_edit_part2(QOF_INSTANCE(bgt), commit_err,
285  noop, gnc_budget_free);
286 }
287 
288 GncBudget*
290 {
291  GncBudget* budget;
292 
293  g_return_val_if_fail(book, NULL);
294 
295  ENTER(" ");
296  budget = g_object_new(GNC_TYPE_BUDGET, NULL);
297  qof_instance_init_data (&budget->inst, GNC_ID_BUDGET, book);
298 
299  qof_event_gen( &budget->inst, QOF_EVENT_CREATE , NULL);
300 
301  LEAVE(" ");
302  return budget;
303 }
304 
305 void
307 {
308  g_return_if_fail(GNC_IS_BUDGET(budget));
309  gnc_budget_begin_edit(budget);
310  qof_instance_set_dirty(&budget->inst);
311  qof_instance_set_destroying(budget, TRUE);
312  gnc_budget_commit_edit(budget);
313 }
314 
316 typedef struct
317 {
318  const GncBudget* old_b;
319  GncBudget* new_b;
320  guint num_periods;
322 
323 static void
324 clone_budget_values_cb(Account* a, gpointer user_data)
325 {
326  CloneBudgetData_t* data = (CloneBudgetData_t*)user_data;
327  guint i;
328 
329  for ( i = 0; i < data->num_periods; ++i )
330  {
331  if ( gnc_budget_is_account_period_value_set(data->old_b, a, i) )
332  {
333  gnc_budget_set_account_period_value(data->new_b, a, i,
334  gnc_budget_get_account_period_value(data->old_b, a, i));
335  }
336  }
337 }
338 
339 GncBudget*
341 {
342  GncBudget* new_b;
343  Account* root;
344  CloneBudgetData_t clone_data;
345 
346  g_return_val_if_fail(old_b != NULL, NULL);
347 
348  ENTER(" ");
349 
350  new_b = gnc_budget_new(qof_instance_get_book(old_b));
351  gnc_budget_begin_edit(new_b);
352  gnc_budget_set_name(new_b, gnc_budget_get_name(old_b));
353  gnc_budget_set_description(new_b, gnc_budget_get_description(old_b));
354  gnc_budget_set_recurrence(new_b, gnc_budget_get_recurrence(old_b));
355  gnc_budget_set_num_periods(new_b, gnc_budget_get_num_periods(old_b));
356 
357  root = gnc_book_get_root_account(qof_instance_get_book(old_b));
358  clone_data.old_b = old_b;
359  clone_data.new_b = new_b;
360  clone_data.num_periods = gnc_budget_get_num_periods(new_b);
361  gnc_account_foreach_descendant(root, clone_budget_values_cb, &clone_data);
362 
363  gnc_budget_commit_edit(new_b);
364 
365  LEAVE(" ");
366 
367  return new_b;
368 }
369 
370 void
371 gnc_budget_set_name(GncBudget* budget, const gchar* name)
372 {
373  BudgetPrivate* priv;
374 
375  g_return_if_fail(GNC_IS_BUDGET(budget) && name);
376 
377  priv = GET_PRIVATE(budget);
378  if ( name == priv->name ) return;
379 
380  gnc_budget_begin_edit(budget);
381  CACHE_REPLACE(priv->name, name);
382  qof_instance_set_dirty(&budget->inst);
383  gnc_budget_commit_edit(budget);
384 
385  qof_event_gen( &budget->inst, QOF_EVENT_MODIFY, NULL);
386 }
387 
388 const gchar*
389 gnc_budget_get_name(const GncBudget* budget)
390 {
391  g_return_val_if_fail(GNC_IS_BUDGET(budget), NULL);
392  return GET_PRIVATE(budget)->name;
393 }
394 
395 void
396 gnc_budget_set_description(GncBudget* budget, const gchar* description)
397 {
398  BudgetPrivate* priv;
399 
400  g_return_if_fail(GNC_IS_BUDGET(budget));
401  g_return_if_fail(description);
402 
403  priv = GET_PRIVATE(budget);
404  if ( description == priv->description ) return;
405  gnc_budget_begin_edit(budget);
406  CACHE_REPLACE(priv->description, description);
407  qof_instance_set_dirty(&budget->inst);
408  gnc_budget_commit_edit(budget);
409 
410  qof_event_gen( &budget->inst, QOF_EVENT_MODIFY, NULL);
411 }
412 
413 const gchar*
414 gnc_budget_get_description(const GncBudget* budget)
415 {
416  g_return_val_if_fail(GNC_IS_BUDGET(budget), NULL);
417  return GET_PRIVATE(budget)->description;
418 }
419 
420 void
421 gnc_budget_set_recurrence(GncBudget *budget, const Recurrence *r)
422 {
423  BudgetPrivate* priv;
424 
425  g_return_if_fail(budget && r);
426  priv = GET_PRIVATE(budget);
427 
428  gnc_budget_begin_edit(budget);
429  priv->recurrence = *r;
430  qof_instance_set_dirty(&budget->inst);
431  gnc_budget_commit_edit(budget);
432 
433  qof_event_gen(&budget->inst, QOF_EVENT_MODIFY, NULL);
434 }
435 
436 const Recurrence *
437 gnc_budget_get_recurrence(const GncBudget *budget)
438 {
439  g_return_val_if_fail(budget, NULL);
440  return (&GET_PRIVATE(budget)->recurrence);
441 }
442 
443 const GncGUID*
444 gnc_budget_get_guid(const GncBudget* budget)
445 {
446  g_return_val_if_fail(budget, NULL);
447  g_return_val_if_fail(GNC_IS_BUDGET(budget), NULL);
448  return qof_instance_get_guid(QOF_INSTANCE(budget));
449 }
450 
451 void
452 gnc_budget_set_num_periods(GncBudget* budget, guint num_periods)
453 {
454  BudgetPrivate* priv;
455 
456  g_return_if_fail(GNC_IS_BUDGET(budget));
457 
458  priv = GET_PRIVATE(budget);
459  if ( priv->num_periods == num_periods ) return;
460 
461  gnc_budget_begin_edit(budget);
462  priv->num_periods = num_periods;
463  qof_instance_set_dirty(&budget->inst);
464  gnc_budget_commit_edit(budget);
465 
466  qof_event_gen( &budget->inst, QOF_EVENT_MODIFY, NULL);
467 }
468 
469 guint
470 gnc_budget_get_num_periods(const GncBudget* budget)
471 {
472  g_return_val_if_fail(GNC_IS_BUDGET(budget), 0);
473  return GET_PRIVATE(budget)->num_periods;
474 }
475 
476 #define BUF_SIZE (10 + GUID_ENCODING_LENGTH + \
477  GNC_BUDGET_MAX_NUM_PERIODS_DIGITS)
478 
479 /* period_num is zero-based */
480 /* What happens when account is deleted, after we have an entry for it? */
481 void
482 gnc_budget_unset_account_period_value(GncBudget *budget, const Account *account,
483  guint period_num)
484 {
485  const GncGUID *guid;
486  KvpFrame *frame;
487  gchar path[BUF_SIZE];
488  gchar *bufend;
489 
490  gnc_budget_begin_edit(budget);
491  frame = qof_instance_get_slots(QOF_INSTANCE(budget));
492  guid = xaccAccountGetGUID(account);
493  bufend = guid_to_string_buff(guid, path);
494  g_sprintf(bufend, "/%d", period_num);
495 
496  kvp_frame_set_value(frame, path, NULL);
497  qof_instance_set_dirty(&budget->inst);
498  gnc_budget_commit_edit(budget);
499 
500  qof_event_gen( &budget->inst, QOF_EVENT_MODIFY, NULL);
501 
502 }
503 
504 /* period_num is zero-based */
505 /* What happens when account is deleted, after we have an entry for it? */
506 void
507 gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
508  guint period_num, gnc_numeric val)
509 {
510  const GncGUID *guid;
511  KvpFrame *frame;
512  gchar path[BUF_SIZE];
513  gchar *bufend;
514 
515  /* Watch out for an off-by-one error here:
516  * period_num starts from 0 while num_periods starts from 1 */
517  if (period_num >= GET_PRIVATE(budget)->num_periods)
518  {
519  PWARN("Period %i does not exist", period_num);
520  return;
521  }
522 
523  gnc_budget_begin_edit(budget);
524  frame = qof_instance_get_slots(QOF_INSTANCE(budget));
525  guid = xaccAccountGetGUID(account);
526  bufend = guid_to_string_buff(guid, path);
527  g_sprintf(bufend, "/%d", period_num);
528 
529  if (gnc_numeric_check(val))
530  kvp_frame_set_value(frame, path, NULL);
531  else
532  kvp_frame_set_numeric(frame, path, val);
533  qof_instance_set_dirty(&budget->inst);
534  gnc_budget_commit_edit(budget);
535 
536  qof_event_gen( &budget->inst, QOF_EVENT_MODIFY, NULL);
537 
538 }
539 
540 /* We don't need these here, but maybe they're useful somewhere else?
541  Maybe this should move to Account.h */
542 
543 gboolean
544 gnc_budget_is_account_period_value_set(const GncBudget *budget, const Account *account,
545  guint period_num)
546 {
547  gchar path[BUF_SIZE];
548  gchar *bufend;
549  KvpFrame *frame;
550 
551  g_return_val_if_fail(GNC_IS_BUDGET(budget), FALSE);
552  g_return_val_if_fail(account, FALSE);
553 
554  frame = qof_instance_get_slots(QOF_INSTANCE(budget));
555  bufend = guid_to_string_buff(xaccAccountGetGUID(account), path);
556  g_sprintf(bufend, "/%d", period_num);
557  return (kvp_frame_get_value(frame, path) != NULL);
558 }
559 
561 gnc_budget_get_account_period_value(const GncBudget *budget, const Account *account,
562  guint period_num)
563 {
565  gchar path[BUF_SIZE];
566  gchar *bufend;
567  KvpFrame *frame;
568 
569  numeric = gnc_numeric_zero();
570  g_return_val_if_fail(GNC_IS_BUDGET(budget), numeric);
571  g_return_val_if_fail(account, numeric);
572 
573  frame = qof_instance_get_slots(QOF_INSTANCE(budget));
574  bufend = guid_to_string_buff(xaccAccountGetGUID(account), path);
575  g_sprintf(bufend, "/%d", period_num);
576 
577  numeric = kvp_frame_get_numeric(frame, path);
578  /* This still returns zero if unset, but callers can check for that. */
579  return numeric;
580 }
581 
582 
583 Timespec
584 gnc_budget_get_period_start_date(const GncBudget *budget, guint period_num)
585 {
586  Timespec ts = {0, 0};
587  g_return_val_if_fail (GNC_IS_BUDGET(budget), ts);
589  &ts, recurrenceGetPeriodTime(&GET_PRIVATE(budget)->recurrence,
590  period_num, FALSE));
591  return ts;
592 }
593 
594 Timespec
595 gnc_budget_get_period_end_date(const GncBudget *budget, guint period_num)
596 {
597  Timespec ts = {0, 0};
598  g_return_val_if_fail (GNC_IS_BUDGET(budget), ts);
600  &ts, recurrenceGetPeriodTime(&GET_PRIVATE(budget)->recurrence, period_num, TRUE));
601  return ts;
602 }
603 
605 gnc_budget_get_account_period_actual_value(
606  const GncBudget *budget, Account *acc, guint period_num)
607 {
608  // FIXME: maybe zero is not best error return val.
609  g_return_val_if_fail(GNC_IS_BUDGET(budget) && acc, gnc_numeric_zero());
610  return recurrenceGetAccountPeriodValue(&GET_PRIVATE(budget)->recurrence,
611  acc, period_num);
612 }
613 
614 GncBudget*
615 gnc_budget_lookup (const GncGUID *guid, const QofBook *book)
616 {
617  QofCollection *col;
618 
619  g_return_val_if_fail(guid, NULL);
620  g_return_val_if_fail(book, NULL);
621  col = qof_book_get_collection (book, GNC_ID_BUDGET);
622  return GNC_BUDGET(qof_collection_lookup_entity (col, guid));
623 }
624 
625 static void just_get_one(QofInstance *ent, gpointer data)
626 {
627  GncBudget **bgt = (GncBudget**)data;
628  if (bgt && !*bgt) *bgt = GNC_BUDGET(ent);
629 }
630 
631 GncBudget*
632 gnc_budget_get_default (QofBook *book)
633 {
634  QofCollection *col;
635  GncBudget *bgt = NULL;
636  const GncGUID *default_budget_guid = NULL;
637 
638  g_return_val_if_fail(book, NULL);
639 
640  /* See if there is a budget selected in the KVP perferences */
641 
642  qof_instance_get (QOF_INSTANCE (book),
643  "default-budget", &default_budget_guid,
644  NULL);
645  if (default_budget_guid != NULL)
646  {
647  col = qof_book_get_collection(book, GNC_ID_BUDGET);
649  default_budget_guid);
650  }
651 
652  /* Revert to 2.2.x behavior if the book has no default budget. */
653 
654  if ( bgt == NULL )
655  {
656  col = qof_book_get_collection(book, GNC_ID_BUDGET);
657  if (qof_collection_count(col) > 0)
658  {
659  qof_collection_foreach(col, just_get_one, &bgt);
660  }
661  }
662 
663  return bgt;
664 }
665 
666 static void
667 destroy_budget_on_book_close(QofInstance *ent, gpointer data)
668 {
669  GncBudget* bgt = GNC_BUDGET(ent);
670 
671  gnc_budget_destroy(bgt);
672 }
673 
678 static void
679 gnc_budget_book_end(QofBook* book)
680 {
681  QofCollection *col;
682 
683  col = qof_book_get_collection(book, GNC_ID_BUDGET);
684  qof_collection_foreach(col, destroy_budget_on_book_close, NULL);
685 }
686 
687 #ifdef _MSC_VER
688 /* MSVC compiler doesn't have C99 "designated initializers"
689  * so we wrap them in a macro that is empty on MSVC. */
690 # define DI(x) /* */
691 #else
692 # define DI(x) x
693 #endif
694 
695 /* Define the QofObject. */
696 static QofObject budget_object_def =
697 {
698  DI(.interface_version = ) QOF_OBJECT_VERSION,
699  DI(.e_type = ) GNC_ID_BUDGET,
700  DI(.type_label = ) "Budget",
701  DI(.create = ) (gpointer)gnc_budget_new,
702  DI(.book_begin = ) NULL,
703  DI(.book_end = ) gnc_budget_book_end,
704  DI(.is_dirty = ) qof_collection_is_dirty,
705  DI(.mark_clean = ) qof_collection_mark_clean,
706  DI(.foreach = ) qof_collection_foreach,
707  DI(.printable = ) (const char * (*)(gpointer)) gnc_budget_get_name,
708  DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
709 };
710 
711 
712 /* Static wrapper getters for the recurrence params */
713 static PeriodType gnc_budget_get_rec_pt(const GncBudget *bgt)
714 {
715  return recurrenceGetPeriodType(&(GET_PRIVATE(bgt)->recurrence));
716 }
717 static guint gnc_budget_get_rec_mult(const GncBudget *bgt)
718 {
719  return recurrenceGetMultiplier(&(GET_PRIVATE(bgt)->recurrence));
720 }
721 static GDate gnc_budget_get_rec_date(const GncBudget *bgt)
722 {
723  return recurrenceGetDate(&(GET_PRIVATE(bgt)->recurrence));
724 }
725 
726 /* Register ourselves with the engine. */
727 gboolean gnc_budget_register (void)
728 {
729  static QofParam params[] =
730  {
731  {
732  "name", QOF_TYPE_STRING,
733  (QofAccessFunc) gnc_budget_get_name,
735  },
736  {
737  "description", QOF_TYPE_STRING,
738  (QofAccessFunc) gnc_budget_get_description,
740  },
741  {
742  "recurrence_period_type", QOF_TYPE_INT32,
743  (QofAccessFunc) gnc_budget_get_rec_pt, NULL
744  },
745  /* Signedness problem: Should be unsigned. */
746  {
747  "recurrence_multiplier", QOF_TYPE_INT32,
748  (QofAccessFunc) gnc_budget_get_rec_mult, NULL
749  },
750  /* This is the same way that SchedXaction.c uses QOF_TYPE_DATE
751  but I don't think QOF actually supports a GDate, so I think
752  this is wrong. */
753  {
754  "recurrence_date", QOF_TYPE_DATE,
755  (QofAccessFunc) gnc_budget_get_rec_date, NULL
756  },
757  /* Signedness problem: Should be unsigned. */
758  {
759  "num_periods", QOF_TYPE_INT32,
760  (QofAccessFunc) gnc_budget_get_num_periods,
762  },
763  {
764  QOF_PARAM_BOOK, QOF_ID_BOOK,
766  },
767  {
768  QOF_PARAM_GUID, QOF_TYPE_GUID,
770  },
771  { NULL },
772  };
773 
774  qof_class_register(GNC_ID_BUDGET, (QofSortFunc) NULL, params);
775  return qof_object_register(&budget_object_def);
776 }
void gnc_budget_set_num_periods(GncBudget *budget, guint num_periods)
Definition: gnc-budget.c:452
void gnc_gdate_set_today(GDate *gd)
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
void gnc_budget_destroy(GncBudget *budget)
Definition: gnc-budget.c:306
Timespec gnc_budget_get_period_end_date(const GncBudget *budget, guint period_num)
Definition: gnc-budget.c:595
const GncGUID * qof_instance_get_guid(gconstpointer)
void qof_instance_get(const QofInstance *inst, const gchar *first_param,...)
Wrapper for g_object_get.
void gnc_account_foreach_descendant(const Account *acc, AccountCb thunk, gpointer user_data)
Definition: Account.c:2958
QofBook * qof_instance_get_book(gconstpointer)
gboolean qof_collection_is_dirty(const QofCollection *col)
QofInstance * qof_collection_lookup_entity(const QofCollection *, const GncGUID *)
QofBackendError
The errors that can be reported to the GUI & other front-end users.
Definition: qofbackend.h:59
GnuCash Budgets.
GncBudget * gnc_budget_new(QofBook *book)
Definition: gnc-budget.c:289
void qof_class_register(QofIdTypeConst obj_name, QofSortFunc default_sort_fcn, const QofParam *params)
Use a 64-bit unsigned int timespec.
Definition: gnc-date.h:299
gchar * guid_to_string_buff(const GncGUID *guid, gchar *buff)
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
Definition: qofclass.h:177
#define QOF_OBJECT_VERSION
Definition: qofobject.h:64
gboolean qof_commit_edit(QofInstance *inst)
#define PERR(format, args...)
Definition: qoflog.h:237
#define ENTER(format, args...)
Definition: qoflog.h:261
#define QOF_PARAM_BOOK
Definition: qofquery.h:109
KvpFrame * kvp_frame_set_value(KvpFrame *frame, const gchar *path, const KvpValue *value)
void qof_collection_foreach(const QofCollection *, QofInstanceForeachCB, gpointer user_data)
Definition: guid.h:65
#define PWARN(format, args...)
Definition: qoflog.h:243
Timespec gnc_budget_get_period_start_date(const GncBudget *budget, guint period_num)
Definition: gnc-budget.c:584
void qof_instance_init_data(QofInstance *, QofIdType, QofBook *)
gboolean qof_begin_edit(QofInstance *inst)
#define xaccAccountGetGUID(X)
Definition: Account.h:239
Definition: finvar.h:98
Account handling public routines.
GncBudget * gnc_budget_clone(const GncBudget *old_b)
Definition: gnc-budget.c:340
void kvp_frame_set_numeric(KvpFrame *frame, const gchar *path, gnc_numeric nval)
int(* QofSortFunc)(gconstpointer, gconstpointer)
Definition: qofclass.h:222
gboolean qof_commit_edit_part2(QofInstance *inst, void(*on_error)(QofInstance *, QofBackendError), void(*on_done)(QofInstance *), void(*on_free)(QofInstance *))
void qof_collection_mark_clean(QofCollection *)
void gnc_budget_set_name(GncBudget *budget, const gchar *name)
Definition: gnc-budget.c:371
GDate helper routines.
void gnc_budget_set_description(GncBudget *budget, const gchar *description)
Definition: gnc-budget.c:396
struct KvpFrameImpl KvpFrame
Definition: kvp_frame.h:76
#define LEAVE(format, args...)
Definition: qoflog.h:271
void(* QofSetterFunc)(gpointer, gpointer)
Definition: qofclass.h:184
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
QofCollection * qof_book_get_collection(const QofBook *, QofIdType)
guint qof_collection_count(const QofCollection *col)
gboolean qof_object_register(const QofObject *object)
void qof_event_gen(QofInstance *entity, QofEventId event_type, gpointer event_data)
Invoke all registered event handlers using the given arguments.
Commodity handling public routines.
const gchar * QofLogModule
Definition: qofid.h:89
void timespecFromTime64(Timespec *ts, time64 t)