GnuCash c935c2f+
Loading...
Searching...
No Matches
gncBillTerm.c
1/********************************************************************\
2 * gncBillTerm.c -- the Gnucash Billing Terms interface *
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 gnu@gnu.org *
20 * *
21\********************************************************************/
22
23/*
24 * Copyright (C) 2002 Derek Atkins
25 * Copyright (C) 2003 Linas Vepstas <linas@linas.org>
26 * Author: Derek Atkins <warlord@MIT.EDU>
27 */
28
29#include <config.h>
30
31#include <glib.h>
32#include <qofinstance-p.h>
33
34#include "gnc-engine.h"
35#include "gncBillTermP.h"
36
38{
39 QofInstance inst;
40
41 /* 'visible' data fields directly manipulated by user */
42 const char * name;
43 const char * desc;
44 GncBillTermType type;
45 gint due_days;
46 gint disc_days;
47 gnc_numeric discount;
48 gint cutoff;
49
50 /* Internal management fields */
51 /* See libgnucash/engine/TaxTableBillTermImmutability.txt for an explanation of the following */
52 /* Code that handles this is *identical* to that in gncTaxTable */
53 gint64 refcount;
54 GncBillTerm * parent; /* if non-null, we are an immutable child */
55 GncBillTerm * child; /* if non-null, we have not changed */
56 gboolean invisible;
57 GList * children; /* list of children for disconnection */
58};
59
61{
62 QofInstanceClass parent_class;
63};
64
66{
67 GList * terms; /* visible terms */
68};
69
70static QofLogModule log_module = GNC_MOD_BUSINESS;
71
72#define _GNC_MOD_NAME GNC_ID_BILLTERM
73
74#define SET_STR(obj, member, str) { \
75 if (!g_strcmp0 (member, str)) return; \
76 gncBillTermBeginEdit (obj); \
77 CACHE_REPLACE(member, str); \
78 }
79
80AS_STRING_DEC(GncBillTermType, ENUM_TERMS_TYPE)
81FROM_STRING_DEC(GncBillTermType, ENUM_TERMS_TYPE)
82
83/* ============================================================== */
84/* Misc inline utilities */
85
86static inline void
87mark_term (GncBillTerm *term)
88{
89 qof_instance_set_dirty(&term->inst);
90 qof_event_gen (&term->inst, QOF_EVENT_MODIFY, NULL);
91}
92
93static inline void maybe_resort_list (GncBillTerm *term)
94{
95 struct _book_info *bi;
96
97 if (term->parent || term->invisible) return;
98 bi = qof_book_get_data (qof_instance_get_book(term), _GNC_MOD_NAME);
99 bi->terms = g_list_sort (bi->terms, (GCompareFunc)gncBillTermCompare);
100}
101
102static inline void addObj (GncBillTerm *term)
103{
104 struct _book_info *bi;
105 bi = qof_book_get_data (qof_instance_get_book(term), _GNC_MOD_NAME);
106 bi->terms = g_list_insert_sorted (bi->terms, term,
107 (GCompareFunc)gncBillTermCompare);
108}
109
110static inline void remObj (GncBillTerm *term)
111{
112 struct _book_info *bi;
113 bi = qof_book_get_data (qof_instance_get_book(term), _GNC_MOD_NAME);
114 bi->terms = g_list_remove (bi->terms, term);
115}
116
117static inline void
118gncBillTermAddChild (GncBillTerm *table, GncBillTerm *child)
119{
120 g_return_if_fail(qof_instance_get_destroying(table) == FALSE);
121 table->children = g_list_prepend(table->children, child);
122}
123
124static inline void
125gncBillTermRemoveChild (GncBillTerm *table, GncBillTerm *child)
126{
128 table->children = g_list_remove(table->children, child);
129}
130
131/* ============================================================== */
132
133enum
134{
135 PROP_0,
136 PROP_NAME
137};
138
139/* GObject Initialization */
140G_DEFINE_TYPE(GncBillTerm, gnc_billterm, QOF_TYPE_INSTANCE)
141
142static void
143gnc_billterm_init(GncBillTerm* bt)
144{
145}
146
147static void
148gnc_billterm_dispose(GObject *btp)
149{
150 G_OBJECT_CLASS(gnc_billterm_parent_class)->dispose(btp);
151}
152
153static void
154gnc_billterm_finalize(GObject* btp)
155{
156 G_OBJECT_CLASS(gnc_billterm_parent_class)->finalize(btp);
157}
158
159static void
160gnc_billterm_get_property (GObject *object,
161 guint prop_id,
162 GValue *value,
163 GParamSpec *pspec)
164{
165 GncBillTerm *bt;
166
167 g_return_if_fail(GNC_IS_BILLTERM(object));
168
169 bt = GNC_BILLTERM(object);
170 switch (prop_id)
171 {
172 case PROP_NAME:
173 g_value_set_string(value, bt->name);
174 break;
175 default:
176 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
177 break;
178 }
179}
180
181static void
182gnc_billterm_set_property (GObject *object,
183 guint prop_id,
184 const GValue *value,
185 GParamSpec *pspec)
186{
187 GncBillTerm *bt;
188
189 g_return_if_fail(GNC_IS_BILLTERM(object));
190
191 bt = GNC_BILLTERM(object);
192 g_assert (qof_instance_get_editlevel(bt));
193
194 switch (prop_id)
195 {
196 case PROP_NAME:
197 gncBillTermSetName(bt, g_value_get_string(value));
198 break;
199 default:
200 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
201 break;
202 }
203}
204
211static GList*
212impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
213{
214 /* Bill term doesn't refer to anything except other billterms */
215 return NULL;
216}
217
218static void
219gnc_billterm_class_init (GncBillTermClass *klass)
220{
221 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
222 QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
223
224 gobject_class->dispose = gnc_billterm_dispose;
225 gobject_class->finalize = gnc_billterm_finalize;
226 gobject_class->set_property = gnc_billterm_set_property;
227 gobject_class->get_property = gnc_billterm_get_property;
228
229 qof_class->get_display_name = NULL;
230 qof_class->refers_to_object = NULL;
231 qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
232
233 g_object_class_install_property
234 (gobject_class,
235 PROP_NAME,
236 g_param_spec_string ("name",
237 "BillTerm Name",
238 "The bill term name is an arbitrary string "
239 "assigned by the user. It is intended to "
240 "a short, 10 to 30 character long string "
241 "that is displayed by the GUI as the "
242 "billterm mnemonic.",
243 NULL,
244 G_PARAM_READWRITE));
245}
246
247/* Create/Destroy Functions */
248GncBillTerm * gncBillTermCreate (QofBook *book)
249{
250 GncBillTerm *term;
251 if (!book) return NULL;
252
253 term = g_object_new (GNC_TYPE_BILLTERM, NULL);
254 qof_instance_init_data(&term->inst, _GNC_MOD_NAME, book);
255 term->name = CACHE_INSERT ("");
256 term->desc = CACHE_INSERT ("");
257 term->discount = gnc_numeric_zero ();
258 addObj (term);
259 qof_event_gen (&term->inst, QOF_EVENT_CREATE, NULL);
260 return term;
261}
262
263void gncBillTermDestroy (GncBillTerm *term)
264{
265 gchar guidstr[GUID_ENCODING_LENGTH+1];
266 if (!term) return;
267 guid_to_string_buff(qof_instance_get_guid(&term->inst),guidstr);
268 DEBUG("destroying bill term %s (%p)", guidstr, term);
269 qof_instance_set_destroying(term, TRUE);
270 qof_instance_set_dirty (&term->inst);
271 gncBillTermCommitEdit (term);
272}
273
274static void gncBillTermFree (GncBillTerm *term)
275{
276 GncBillTerm *child;
277 GList *list;
278
279 if (!term) return;
280
281 qof_event_gen (&term->inst, QOF_EVENT_DESTROY, NULL);
282 CACHE_REMOVE (term->name);
283 CACHE_REMOVE (term->desc);
284 remObj (term);
285
287 PERR("free a billterm without do_free set!");
288
289 /* disconnect from parent */
290 if (term->parent)
291 gncBillTermRemoveChild(term->parent, term);
292
293 /* disconnect from the children */
294 for (list = term->children; list; list = list->next)
295 {
296 child = list->data;
297 gncBillTermSetParent(child, NULL);
298 }
299 g_list_free(term->children);
300
301 /* qof_instance_release(&term->inst); */
302 g_object_unref (term);
303}
304
305/* ============================================================== */
306/* Set Functions */
307
308void gncBillTermSetName (GncBillTerm *term, const char *name)
309{
310 if (!term || !name) return;
311 SET_STR (term, term->name, name);
312 mark_term (term);
313 maybe_resort_list (term);
314 gncBillTermCommitEdit (term);
315}
316
317void gncBillTermSetDescription (GncBillTerm *term, const char *desc)
318{
319 if (!term || !desc) return;
320 SET_STR (term, term->desc, desc);
321 mark_term (term);
322 maybe_resort_list (term);
323 gncBillTermCommitEdit (term);
324}
325
326void gncBillTermSetType (GncBillTerm *term, GncBillTermType type)
327{
328 if (!term) return;
329 if (term->type == type) return;
330 gncBillTermBeginEdit (term);
331 term->type = type;
332 mark_term (term);
333 gncBillTermCommitEdit (term);
334}
335
337FROM_STRING_FUNC(GncBillTermType, ENUM_TERMS_TYPE)
338
339static
340void qofBillTermSetType (GncBillTerm *term, const char *type_label)
341{
342 GncBillTermType type;
343
344 type = GncBillTermTypefromString(type_label);
345 gncBillTermSetType(term, type);
346}
347
348void gncBillTermSetDueDays (GncBillTerm *term, gint days)
349{
350 if (!term) return;
351 if (term->due_days == days) return;
352 gncBillTermBeginEdit (term);
353 term->due_days = days;
354 mark_term (term);
355 gncBillTermCommitEdit (term);
356}
357
358void gncBillTermSetDiscountDays (GncBillTerm *term, gint days)
359{
360 if (!term) return;
361 if (term->disc_days == days) return;
362 gncBillTermBeginEdit (term);
363 term->disc_days = days;
364 mark_term (term);
365 gncBillTermCommitEdit (term);
366}
367
368void gncBillTermSetDiscount (GncBillTerm *term, gnc_numeric discount)
369{
370 if (!term) return;
371 if (gnc_numeric_eq (term->discount, discount)) return;
372 gncBillTermBeginEdit (term);
373 term->discount = discount;
374 mark_term (term);
375 gncBillTermCommitEdit (term);
376}
377
378void gncBillTermSetCutoff (GncBillTerm *term, gint cutoff)
379{
380 if (!term) return;
381 if (term->cutoff == cutoff) return;
382 gncBillTermBeginEdit (term);
383 term->cutoff = cutoff;
384 mark_term (term);
385 gncBillTermCommitEdit (term);
386}
387
388/* XXX this doesn't seem right. If the parent/child relationship
389 * is a doubly-linked list, then there shouldn't be separate set-parent,
390 * set-child routines, else misuse of the routines will goof up
391 * relationships. These ops should be atomic, I think.
392 */
393void gncBillTermSetParent (GncBillTerm *term, GncBillTerm *parent)
394{
395 if (!term) return;
396 gncBillTermBeginEdit (term);
397 if (term->parent)
398 gncBillTermRemoveChild(term->parent, term);
399 term->parent = parent;
400 if (parent)
401 gncBillTermAddChild(parent, term);
402 term->refcount = 0;
403 if ( parent != NULL )
404 {
405 gncBillTermMakeInvisible (term);
406 }
407 mark_term (term);
408 gncBillTermCommitEdit (term);
409}
410
411void gncBillTermSetChild (GncBillTerm *term, GncBillTerm *child)
412{
413 if (!term) return;
414 gncBillTermBeginEdit (term);
415 term->child = child;
416 mark_term (term);
417 gncBillTermCommitEdit (term);
418}
419
420void gncBillTermIncRef (GncBillTerm *term)
421{
422 if (!term) return;
423 if (term->parent || term->invisible) return; /* children dont need refcounts */
424 gncBillTermBeginEdit (term);
425 term->refcount++;
426 mark_term (term);
427 gncBillTermCommitEdit (term);
428}
429
430void gncBillTermDecRef (GncBillTerm *term)
431{
432 if (!term) return;
433 if (term->parent || term->invisible) return; /* children dont need refcounts */
434 g_return_if_fail (term->refcount >= 1);
435 gncBillTermBeginEdit (term);
436 term->refcount--;
437 mark_term (term);
438 gncBillTermCommitEdit (term);
439}
440
441void gncBillTermSetRefcount (GncBillTerm *term, gint64 refcount)
442{
443 if (!term) return;
444 gncBillTermBeginEdit (term);
445 term->refcount = refcount;
446 mark_term (term);
447 gncBillTermCommitEdit (term);
448}
449
450void gncBillTermMakeInvisible (GncBillTerm *term)
451{
452 if (!term) return;
453 gncBillTermBeginEdit (term);
454 term->invisible = TRUE;
455 remObj (term);
456 mark_term (term);
457 gncBillTermCommitEdit (term);
458}
459
460void gncBillTermChanged (GncBillTerm *term)
461{
462 if (!term) return;
463 term->child = NULL;
464}
465
466void gncBillTermBeginEdit (GncBillTerm *term)
467{
468 qof_begin_edit(&term->inst);
469}
470
471static void gncBillTermOnError (QofInstance *inst, QofBackendError errcode)
472{
473 PERR("BillTerm QofBackend Failure: %d", errcode);
474 gnc_engine_signal_commit_error( errcode );
475}
476
477static void bill_free (QofInstance *inst)
478{
479 GncBillTerm *term = (GncBillTerm *) inst;
480 gncBillTermFree(term);
481}
482
483static void on_done (QofInstance *inst) {}
484
485void gncBillTermCommitEdit (GncBillTerm *term)
486{
487 if (!qof_commit_edit (QOF_INSTANCE(term))) return;
488 qof_commit_edit_part2 (&term->inst, gncBillTermOnError,
489 on_done, bill_free);
490}
491
492/* Get Functions */
493
494GncBillTerm *gncBillTermLookupByName (QofBook *book, const char *name)
495{
496 GList *list = gncBillTermGetTerms (book);
497
498 for ( ; list; list = list->next)
499 {
500 GncBillTerm *term = list->data;
501 if (!g_strcmp0 (term->name, name))
502 return list->data;
503 }
504 return NULL;
505}
506
507GList * gncBillTermGetTerms (QofBook *book)
508{
509 struct _book_info *bi;
510 if (!book) return NULL;
511
512 bi = qof_book_get_data (book, _GNC_MOD_NAME);
513 return bi->terms;
514}
515
516const char *gncBillTermGetName (const GncBillTerm *term)
517{
518 if (!term) return NULL;
519 return term->name;
520}
521
522const char *gncBillTermGetDescription (const GncBillTerm *term)
523{
524 if (!term) return NULL;
525 return term->desc;
526}
527
528GncBillTermType gncBillTermGetType (const GncBillTerm *term)
529{
530 if (!term) return 0;
531 return term->type;
532}
533
535AS_STRING_FUNC(GncBillTermType, ENUM_TERMS_TYPE)
536
537static
538const char* qofBillTermGetType (const GncBillTerm *term)
539{
540 if (!term)
541 {
542 return NULL;
543 }
544 return GncBillTermTypeasString(term->type);
545}
546
547gint gncBillTermGetDueDays (const GncBillTerm *term)
548{
549 if (!term) return 0;
550 return term->due_days;
551}
552
553gint gncBillTermGetDiscountDays (const GncBillTerm *term)
554{
555 if (!term) return 0;
556 return term->disc_days;
557}
558
559gnc_numeric gncBillTermGetDiscount (const GncBillTerm *term)
560{
561 if (!term) return gnc_numeric_zero ();
562 return term->discount;
563}
564
565gint gncBillTermGetCutoff (const GncBillTerm *term)
566{
567 if (!term) return 0;
568 return term->cutoff;
569}
570
571static GncBillTerm *gncBillTermCopy (const GncBillTerm *term)
572{
573 GncBillTerm *t;
574
575 if (!term) return NULL;
576 t = gncBillTermCreate (qof_instance_get_book(term));
577
578 gncBillTermBeginEdit(t);
579
580 gncBillTermSetName (t, term->name);
581 gncBillTermSetDescription (t, term->desc);
582
583 t->type = term->type;
584 t->due_days = term->due_days;
585 t->disc_days = term->disc_days;
586 t->discount = term->discount;
587 t->cutoff = term->cutoff;
588
589 mark_term (t);
590 gncBillTermCommitEdit(t);
591
592 return t;
593}
594
595GncBillTerm *gncBillTermReturnChild (GncBillTerm *term, gboolean make_new)
596{
597 GncBillTerm *child = NULL;
598
599 if (!term) return NULL;
600 if (term->child) return term->child;
601 if (term->parent || term->invisible) return term;
602 if (make_new)
603 {
604 child = gncBillTermCopy (term);
605 gncBillTermSetChild (term, child);
606 gncBillTermSetParent (child, term);
607 }
608 return child;
609}
610
611GncBillTerm *gncBillTermGetParent (const GncBillTerm *term)
612{
613 if (!term) return NULL;
614 return term->parent;
615}
616
617gint64 gncBillTermGetRefcount (const GncBillTerm *term)
618{
619 if (!term) return 0;
620 return term->refcount;
621}
622
623gboolean gncBillTermGetInvisible (const GncBillTerm *term)
624{
625 if (!term) return FALSE;
626 return term->invisible;
627}
628
629int gncBillTermCompare (const GncBillTerm *a, const GncBillTerm *b)
630{
631 int ret;
632
633 if (!a && !b) return 0;
634 if (!a) return -1;
635 if (!b) return 1;
636
637 ret = g_strcmp0 (a->name, b->name);
638 if (ret) return ret;
639
640 return g_strcmp0 (a->desc, b->desc);
641}
642
643gboolean gncBillTermEqual(const GncBillTerm *a, const GncBillTerm *b)
644{
645 if (a == NULL && b == NULL) return TRUE;
646 if (a == NULL || b == NULL) return FALSE;
647
648 g_return_val_if_fail(GNC_IS_BILLTERM(a), FALSE);
649 g_return_val_if_fail(GNC_IS_BILLTERM(b), FALSE);
650
651 if (g_strcmp0(a->name, b->name) != 0)
652 {
653 PWARN("Names differ: %s vs %s", a->name, b->name);
654 return FALSE;
655 }
656
657 if (g_strcmp0(a->desc, b->desc) != 0)
658 {
659 PWARN("Descriptions differ: %s vs %s", a->desc, b->desc);
660 return FALSE;
661 }
662
663 if (a->type != b->type)
664 {
665 PWARN("Types differ");
666 return FALSE;
667 }
668
669 if (a->due_days != b->due_days)
670 {
671 PWARN("Due days differ: %d vs %d", a->due_days, b->due_days);
672 return FALSE;
673 }
674
675 if (a->disc_days != b->disc_days)
676 {
677 PWARN("Discount days differ: %d vs %d", a->disc_days, b->disc_days);
678 return FALSE;
679 }
680
681 if (!gnc_numeric_equal(a->discount, b->discount))
682 {
683 PWARN("Discounts differ");
684 return FALSE;
685 }
686
687 if (a->cutoff != b->cutoff)
688 {
689 PWARN("Cutoffs differ: %d vs %d", a->cutoff, b->cutoff);
690 return FALSE;
691 }
692
693 if (a->invisible != b->invisible)
694 {
695 PWARN("Invisible flags differ");
696 return FALSE;
697 }
698
699// gint64 refcount;
700// GncBillTerm * parent; /* if non-null, we are an immutable child */
701// GncBillTerm * child; /* if non-null, we have not changed */
702// GList * children; /* list of children for disconnection */
703
704 return TRUE;
705}
706
707gboolean gncBillTermIsFamily (const GncBillTerm *a, const GncBillTerm *b)
708{
709 if (!gncBillTermCompare (a, b))
710 return TRUE;
711 else
712 return FALSE;
713}
714
715gboolean gncBillTermIsDirty (const GncBillTerm *term)
716{
717 if (!term) return FALSE;
718 return qof_instance_get_dirty_flag(term);
719}
720
721/********************************************************/
722/* functions to compute dates from Bill Terms */
723
724#define SECS_PER_DAY 86400
725
726/* Based on the post date and a proximo type, compute the month and
727 * year this is due. The actual day is filled in below.
728 *
729 * A proximo billing term has multiple parameters:
730 * * due day: day of the month the invoice/bill will be due
731 * * cutoff: day of the month used to decide if the due date will be
732 * in the next month or in the month thereafter. This can be
733 * a negative number in which case the cutoff date is relative
734 * to the end of the month and counting backwards.
735 * Eg: cutoff = -3 would mean 25 in February or 28 in June
736 *
737 * How does it work:
738 * Assume cutoff = 19 and due day = 20
739 *
740 * * Example 1 post date = 14-06-2010 (European date format)
741 * 14 is less than the cutoff of 19, so the due date will be in the next
742 * month. Since the due day is set to 20, the due date will be
743 * 20-07-2010
744 *
745 * * Example 2 post date = 22-06-2010 (European date format)
746 * 22 is more than the cutoff of 19, so the due date will be in the month
747 * after next month. Since the due day is set to 20, the due date will be
748 * 20-02-2010
749 *
750 */
751static void
752compute_monthyear (const GncBillTerm *term, time64 post_date,
753 int *month, int *year)
754{
755 int iday, imonth, iyear;
756 struct tm tm;
757 int cutoff = term->cutoff;
758
759 g_return_if_fail (term->type == GNC_TERM_TYPE_PROXIMO);
760 gnc_localtime_r (&post_date, &tm);
761 iday = tm.tm_mday;
762 imonth = tm.tm_mon + 1;
763 iyear = tm.tm_year + 1900;
764
765 if (cutoff <= 0)
766 cutoff += gnc_date_get_last_mday (imonth - 1, iyear);
767
768 if (iday <= cutoff)
769 {
770 /* We apply this to next month */
771 imonth++;
772 }
773 else
774 {
775 /* We apply to the following month */
776 imonth += 2;
777 }
778
779 if (imonth > 12)
780 {
781 iyear++;
782 imonth -= 12;
783 }
784
785 if (month) *month = imonth;
786 if (year) *year = iyear;
787}
788
789/* There are two types of billing terms:
790 *
791 * Type DAYS defines a due date to be a fixed number of days passed the post
792 * date. This is a straightforward calculation.
793 *
794 * The other type PROXIMO defines the due date as a fixed day of the month
795 * (like always the 15th of the month). The proximo algorithm determines which
796 * month based on the cutoff day and the post date. See above for a more
797 * detailed explanation of proximo.
798 */
799
800static time64
801compute_time (const GncBillTerm *term, time64 post_date, int days)
802{
803 time64 res = gnc_time64_get_day_neutral (post_date);
804 int day, month, year;
805
806 switch (term->type)
807 {
808 case GNC_TERM_TYPE_DAYS:
809 res += (SECS_PER_DAY * days);
810 res = gnc_time64_get_day_neutral (res);
811 break;
812 case GNC_TERM_TYPE_PROXIMO:
813 compute_monthyear (term, post_date, &month, &year);
814 day = gnc_date_get_last_mday (month - 1, year);
815 if (days < day)
816 day = days;
817 res = gnc_dmy2time64_neutral (day, month, year);
818 break;
819 }
820 return res;
821}
822
823time64
824gncBillTermComputeDueDate (const GncBillTerm *term, time64 post_date)
825{
826 if (!term) return post_date;
827 return compute_time (term, post_date, term->due_days);
828}
829
830/* Package-Private functions */
831
832static void _gncBillTermCreate (QofBook *book)
833{
834 struct _book_info *bi;
835
836 if (!book) return;
837
838 bi = g_new0 (struct _book_info, 1);
839 qof_book_set_data (book, _GNC_MOD_NAME, bi);
840}
841
842
843static void
844destroy_billterm_on_book_close (QofInstance *ent, gpointer data)
845{
846 GncBillTerm *term = GNC_BILLTERM(ent);
847
848 gncBillTermBeginEdit (term);
849 gncBillTermDestroy (term);
850}
851
852static void _gncBillTermDestroy (QofBook *book)
853{
854 struct _book_info *bi;
855 QofCollection *col;
856
857 if (!book) return;
858
859 bi = qof_book_get_data (book, _GNC_MOD_NAME);
860
861 col = qof_book_get_collection (book, GNC_ID_BILLTERM);
862 qof_collection_foreach (col, destroy_billterm_on_book_close, NULL);
863
864 g_list_free (bi->terms);
865 g_free (bi);
866}
867
868static QofObject gncBillTermDesc =
869{
870 DI(.interface_version = ) QOF_OBJECT_VERSION,
871 DI(.e_type = ) _GNC_MOD_NAME,
872 DI(.type_label = ) "Billing Term",
873 DI(.create = ) (gpointer)gncBillTermCreate,
874 DI(.book_begin = ) _gncBillTermCreate,
875 DI(.book_end = ) _gncBillTermDestroy,
876 DI(.is_dirty = ) qof_collection_is_dirty,
877 DI(.mark_clean = ) qof_collection_mark_clean,
878 DI(.foreach = ) qof_collection_foreach,
879 DI(.printable = ) NULL,
880 DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
881};
882
883gboolean gncBillTermRegister (void)
884{
885 static QofParam params[] =
886 {
887 { GNC_BILLTERM_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncBillTermGetName, (QofSetterFunc)gncBillTermSetName },
888 { GNC_BILLTERM_DESC, QOF_TYPE_STRING, (QofAccessFunc)gncBillTermGetDescription, (QofSetterFunc)gncBillTermSetDescription },
889 { GNC_BILLTERM_TYPE, QOF_TYPE_STRING, (QofAccessFunc)qofBillTermGetType, (QofSetterFunc)qofBillTermSetType },
890 { GNC_BILLTERM_DUEDAYS, QOF_TYPE_INT32, (QofAccessFunc)gncBillTermGetDueDays, (QofSetterFunc)gncBillTermSetDueDays },
891 { GNC_BILLTERM_DISCDAYS, QOF_TYPE_INT32, (QofAccessFunc)gncBillTermGetDiscountDays, (QofSetterFunc)gncBillTermSetDiscountDays },
892 { GNC_BILLTERM_DISCOUNT, QOF_TYPE_NUMERIC, (QofAccessFunc)gncBillTermGetDiscount, (QofSetterFunc)gncBillTermSetDiscount },
893 { GNC_BILLTERM_CUTOFF, QOF_TYPE_INT32, (QofAccessFunc)gncBillTermGetCutoff, (QofSetterFunc)gncBillTermSetCutoff },
894 { GNC_BILLTERM_REFCOUNT, QOF_TYPE_INT64, (QofAccessFunc)gncBillTermGetRefcount, NULL },
895 { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
896 { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
897 { NULL },
898 };
899
900 qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncBillTermCompare, params);
901
902 return qof_object_register (&gncBillTermDesc);
903}
All type declarations for the whole Gnucash engine.
QofBackendError
The errors that can be reported to the GUI & other front-end users.
Definition qofbackend.h:58
gboolean gncBillTermEqual(const GncBillTerm *a, const GncBillTerm *b)
Check if all internal fields of a and b match.
int gncBillTermCompare(const GncBillTerm *a, const GncBillTerm *b)
Compare BillTerms on their name for sorting.
#define ENUM_TERMS_TYPE(_)
How to interpret the amount.
gboolean gncBillTermIsFamily(const GncBillTerm *a, const GncBillTerm *b)
Check only if the bill terms are "family".
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
Definition qofbook.cpp:521
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
The QofAccessFunc defines an arbitrary function pointer for access functions.
Definition qofclass.h:123
void(* QofSetterFunc)(gpointer, gpointer)
The QofSetterFunc defines an function pointer for parameter setters.
Definition qofclass.h:130
void qof_class_register(QofIdTypeConst obj_name, QofSortFunc default_sort_function, const QofParam *params)
This function registers a new object class with the Qof subsystem.
Definition qofclass.cpp:86
int(* QofSortFunc)(gconstpointer, gconstpointer)
This function is the default sort function for a particular object type.
Definition qofclass.h:168
int gnc_date_get_last_mday(int month, int year)
Get the numerical last date of the month.
Definition gnc-date.cpp:413
struct tm * gnc_localtime_r(const time64 *secs, struct tm *time)
fill out a time struct from a 64-bit time value adjusted for the current time zone.
Definition gnc-date.cpp:115
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition gnc-date.h:87
time64 gnc_time64_get_day_neutral(time64 time_val)
The gnc_time64_get_day_neutral() routine will take the given time in seconds and adjust it to 10:59:0...
gboolean qof_collection_is_dirty(const QofCollection *col)
Return value of 'dirty' flag on collection.
Definition qofid.cpp:232
void qof_event_gen(QofInstance *entity, QofEventId event_id, gpointer event_data)
Invoke all registered event handlers using the given arguments.
Definition qofevent.cpp:231
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
Definition guid.h:84
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
Definition guid.cpp:208
QofBook * qof_instance_get_book(gconstpointer inst)
Return the book pointer.
const GncGUID * qof_instance_get_guid(gconstpointer inst)
Return the GncGUID of this instance.
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
Compare two instances, based on their last update times.
void qof_instance_init_data(QofInstance *inst, QofIdType type, QofBook *book)
Initialise the settings associated with an instance.
gboolean qof_instance_get_dirty_flag(gconstpointer ptr)
Retrieve the flag that indicates whether or not this object has been modified.
gboolean qof_instance_get_destroying(gconstpointer ptr)
Retrieve the flag that indicates whether or not this object is about to be destroyed.
#define DEBUG(format, args...)
Print a debugging message.
Definition qoflog.h:264
#define PERR(format, args...)
Log a serious error.
Definition qoflog.h:244
#define PWARN(format, args...)
Log a warning.
Definition qoflog.h:250
gboolean gnc_numeric_eq(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b are exactly the same (have the same numerator and ...
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b represent the same number.
void qof_collection_mark_clean(QofCollection *)
reset value of dirty flag
Definition qofid.cpp:238
#define QOF_OBJECT_VERSION
Defines the version of the core object object registration interface.
Definition qofobject.h:63
gboolean qof_object_register(const QofObject *object)
Register new types of object objects.
#define QOF_PARAM_BOOK
"Known" Object Parameters – all objects must support these
Definition qofquery.h:108
gboolean qof_commit_edit_part2(QofInstance *inst, void(*on_error)(QofInstance *, QofBackendError), void(*on_done)(QofInstance *), void(*on_free)(QofInstance *))
part2 – deal with the backend
gboolean qof_commit_edit(QofInstance *inst)
commit_edit helpers
gboolean qof_begin_edit(QofInstance *inst)
begin_edit
QofBook reference.
Definition qofbook-p.hpp:47