GnuCash  5.6-150-g038405b370+
gncVendor.c
1 /********************************************************************\
2  * gncVendor.c -- the Core Vendor 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) 2001, 2002 Derek Atkins
25  * Copyright (C) 2003 <linas@linas.org>
26  * Author: Derek Atkins <warlord@MIT.EDU>
27  */
28 
29 #include <config.h>
30 
31 #include <glib.h>
32 #include <string.h>
33 #include <qofinstance-p.h>
34 
35 #include "gnc-commodity.h"
36 #include "gncAddressP.h"
37 #include "gncBillTermP.h"
38 #include "gncInvoice.h"
39 #include "gncJobP.h"
40 #include "gncTaxTableP.h"
41 #include "gncVendor.h"
42 #include "gncVendorP.h"
43 
44 static gint vend_qof_event_handler_id = 0;
45 static void vend_handle_qof_events (QofInstance *entity, QofEventId event_type,
46  gpointer user_data, gpointer event_data);
47 static void qofVendorSetAddr (GncVendor *vendor, QofInstance *addr_ent);
48 static const char* qofVendorGetTaxIncluded(const GncVendor *vendor);
49 static void qofVendorSetTaxIncluded(GncVendor *vendor, const char* type_string);
50 
51 struct _gncVendor
52 {
53  QofInstance inst;
54 
55  const char * id;
56  const char * name;
57  const char * notes;
58  GncBillTerm * terms;
59  GncAddress * addr;
60  gnc_commodity * currency;
61  GncTaxTable* taxtable;
62  gboolean taxtable_override;
63  GncTaxIncluded taxincluded;
64  gboolean active;
65  GList * jobs;
66  gnc_numeric * balance; /* cached vendor balance, will not be stored */
67 };
68 
70 {
71  QofInstanceClass parent_class;
72 };
73 
74 static QofLogModule log_module = GNC_MOD_BUSINESS;
75 
76 #define _GNC_MOD_NAME GNC_ID_VENDOR
77 
78 /* ============================================================ */
79 /* Misc inline funcs */
80 
81 static inline void mark_vendor (GncVendor *vendor);
82 void mark_vendor (GncVendor *vendor)
83 {
84  qof_instance_set_dirty(&vendor->inst);
85  qof_event_gen (&vendor->inst, QOF_EVENT_MODIFY, NULL);
86 }
87 
88 /* ============================================================== */
89 
90 enum
91 {
92  PROP_0,
93  PROP_NAME, /* Table */
94  PROP_ID, /* Table */
95  PROP_NOTES, /* Table */
96  PROP_CURRENCY, /* Table */
97  PROP_ACTIVE, /* Table */
98  PROP_TAXTABLE_OVERRIDE, /* Table */
99  PROP_BILLTERMS, /* Table */
100  PROP_TAXTABLE, /* Table */
101  PROP_ADDRESS, /* Table, 8 fields */
102  PROP_TAX_INCLUDED, /* Table */
103  PROP_TAX_INCLUDED_STR, /* Alternate setter for PROP_TAX_INCLUDED */
104  PROP_PDF_DIRNAME, /* KVP */
105  PROP_LAST_POSTED, /* KVP */
106  PROP_PAYMENT_LAST_ACCT, /* KVP */
107 };
108 
109 /* GObject Initialization */
110 G_DEFINE_TYPE(GncVendor, gnc_vendor, QOF_TYPE_INSTANCE)
111 
112 static void
113 gnc_vendor_init(GncVendor* vendor)
114 {
115 }
116 
117 static void
118 gnc_vendor_dispose(GObject *vendorp)
119 {
120  G_OBJECT_CLASS(gnc_vendor_parent_class)->dispose(vendorp);
121 }
122 
123 static void
124 gnc_vendor_finalize(GObject* vendorp)
125 {
126  G_OBJECT_CLASS(gnc_vendor_parent_class)->finalize(vendorp);
127 }
128 
129 /* Note that g_value_set_object() refs the object, as does
130  * g_object_get(). But g_object_get() only unrefs once when it disgorges
131  * the object, leaving an unbalanced ref, which leaks. So instead of
132  * using g_value_set_object(), use g_value_take_object() which doesn't
133  * ref the object when used in get_property().
134  */
135 static void
136 gnc_vendor_get_property (GObject *object,
137  guint prop_id,
138  GValue *value,
139  GParamSpec *pspec)
140 {
141  GncVendor *vendor;
142 
143  g_return_if_fail(GNC_IS_VENDOR(object));
144 
145  vendor = GNC_VENDOR(object);
146  switch (prop_id)
147  {
148  case PROP_NAME:
149  g_value_set_string(value, vendor->name);
150  break;
151  case PROP_ID:
152  g_value_set_string(value, vendor->id);
153  break;
154  case PROP_NOTES:
155  g_value_set_string(value, vendor->notes);
156  break;
157  case PROP_CURRENCY:
158  g_value_take_object(value, vendor->currency);
159  break;
160  case PROP_ACTIVE:
161  g_value_set_boolean(value, vendor->active);
162  break;
163  case PROP_TAXTABLE_OVERRIDE:
164  g_value_set_boolean(value, vendor->taxtable_override);
165  break;
166  case PROP_BILLTERMS:
167  g_value_take_object(value, vendor->terms);
168  break;
169  case PROP_TAXTABLE:
170  g_value_take_object(value, vendor->taxtable);
171  break;
172  case PROP_ADDRESS:
173  g_value_take_object(value, vendor->addr);
174  break;
175  case PROP_TAX_INCLUDED:
176  g_value_set_int(value, vendor->taxincluded);
177  break;
178  case PROP_TAX_INCLUDED_STR:
179  g_value_set_string(value, qofVendorGetTaxIncluded(vendor));
180  break;
181  case PROP_PDF_DIRNAME:
182  qof_instance_get_kvp (QOF_INSTANCE (vendor), value, 1, OWNER_EXPORT_PDF_DIRNAME);
183  break;
184  case PROP_LAST_POSTED:
185  qof_instance_get_kvp (QOF_INSTANCE (vendor), value, 1, LAST_POSTED_TO_ACCT);
186  break;
187  case PROP_PAYMENT_LAST_ACCT:
188  qof_instance_get_kvp (QOF_INSTANCE (vendor), value, 2, GNC_PAYMENT, GNC_LAST_ACCOUNT);
189  break;
190  default:
191  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
192  break;
193  }
194 }
195 
196 static void
197 gnc_vendor_set_property (GObject *object,
198  guint prop_id,
199  const GValue *value,
200  GParamSpec *pspec)
201 {
202  GncVendor *vendor;
203 
204  g_return_if_fail(GNC_IS_VENDOR(object));
205 
206  vendor = GNC_VENDOR(object);
207  g_assert (qof_instance_get_editlevel(vendor));
208 
209  switch (prop_id)
210  {
211  case PROP_NAME:
212  gncVendorSetName(vendor, g_value_get_string(value));
213  break;
214  case PROP_ID:
215  gncVendorSetID(vendor, g_value_get_string(value));
216  break;
217  case PROP_NOTES:
218  gncVendorSetNotes(vendor, g_value_get_string(value));
219  break;
220  case PROP_CURRENCY:
221  gncVendorSetCurrency(vendor, g_value_get_object(value));
222  break;
223  case PROP_ACTIVE:
224  gncVendorSetActive(vendor, g_value_get_boolean(value));
225  break;
226  case PROP_TAXTABLE_OVERRIDE:
227  gncVendorSetTaxTableOverride(vendor, g_value_get_boolean(value));
228  break;
229  case PROP_BILLTERMS:
230  gncVendorSetTerms(vendor, g_value_get_object(value));
231  break;
232  case PROP_TAXTABLE:
233  gncVendorSetTaxTable(vendor, g_value_get_object(value));
234  break;
235  case PROP_ADDRESS:
236  qofVendorSetAddr(vendor, g_value_get_object(value));
237  break;
238  case PROP_TAX_INCLUDED:
239  gncVendorSetTaxIncluded(vendor, (GncTaxIncluded)g_value_get_int(value));
240  break;
241  case PROP_TAX_INCLUDED_STR:
242  qofVendorSetTaxIncluded(vendor, g_value_get_string(value));
243  break;
244  case PROP_PDF_DIRNAME:
245  qof_instance_set_kvp (QOF_INSTANCE (vendor), value, 1, OWNER_EXPORT_PDF_DIRNAME);
246  break;
247  case PROP_LAST_POSTED:
248  qof_instance_set_kvp (QOF_INSTANCE (vendor), value, 1, LAST_POSTED_TO_ACCT);
249  break;
250  case PROP_PAYMENT_LAST_ACCT:
251  qof_instance_set_kvp (QOF_INSTANCE (vendor), value, 2, GNC_PAYMENT, GNC_LAST_ACCOUNT);
252  break;
253  default:
254  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
255  break;
256  }
257 }
258 
260 static gboolean
261 impl_refers_to_object(const QofInstance* inst, const QofInstance* ref)
262 {
263  GncVendor* v;
264 
265  g_return_val_if_fail(inst != NULL, FALSE);
266  g_return_val_if_fail(GNC_IS_VENDOR(inst), FALSE);
267 
268  v = GNC_VENDOR(inst);
269 
270  if (GNC_IS_BILLTERM(ref))
271  {
272  return (v->terms == GNC_BILLTERM(ref));
273  }
274  else if (GNC_IS_TAXTABLE(ref))
275  {
276  return (v->taxtable == GNC_TAXTABLE(ref));
277  }
278 
279  return FALSE;
280 }
281 
288 static GList*
289 impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
290 {
291  if (!GNC_IS_BILLTERM(ref) && !GNC_IS_TAXTABLE(ref))
292  {
293  return NULL;
294  }
295 
297 }
298 
299 static void
300 gnc_vendor_class_init (GncVendorClass *klass)
301 {
302  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
303  QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
304 
305  gobject_class->dispose = gnc_vendor_dispose;
306  gobject_class->finalize = gnc_vendor_finalize;
307  gobject_class->set_property = gnc_vendor_set_property;
308  gobject_class->get_property = gnc_vendor_get_property;
309 
310  qof_class->get_display_name = NULL;
311  qof_class->refers_to_object = impl_refers_to_object;
312  qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
313 
314  g_object_class_install_property
315  (gobject_class,
316  PROP_NAME,
317  g_param_spec_string ("name",
318  "Vendor Name",
319  "The vendor name is an arbitrary string "
320  "assigned by the user to provide the vendor name.",
321  NULL,
322  G_PARAM_READWRITE));
323 
324  g_object_class_install_property
325  (gobject_class,
326  PROP_ID,
327  g_param_spec_string ("id",
328  "Vendor ID",
329  "The vendor id is an arbitrary string "
330  "assigned by the user to identify the vendor.",
331  NULL,
332  G_PARAM_READWRITE));
333 
334  g_object_class_install_property
335  (gobject_class,
336  PROP_NOTES,
337  g_param_spec_string ("notes",
338  "Vendor notes",
339  "The vendor notes is an arbitrary string "
340  "assigned by the user to add extra information about the vendor.",
341  NULL,
342  G_PARAM_READWRITE));
343 
344  g_object_class_install_property
345  (gobject_class,
346  PROP_CURRENCY,
347  g_param_spec_object ("currency",
348  "Currency",
349  "The currency property denotes the currency used by this vendor.",
350  GNC_TYPE_COMMODITY,
351  G_PARAM_READWRITE));
352 
353  g_object_class_install_property
354  (gobject_class,
355  PROP_ACTIVE,
356  g_param_spec_boolean ("active",
357  "Active",
358  "TRUE if the vendor is active. FALSE if inactive.",
359  FALSE,
360  G_PARAM_READWRITE));
361 
362  g_object_class_install_property
363  (gobject_class,
364  PROP_TAXTABLE_OVERRIDE,
365  g_param_spec_boolean ("tax-table-override",
366  "Tax table override",
367  "TRUE if the vendor has a specific tax table which overrides the default "
368  "tax table. FALSE if the default table should be used.",
369  FALSE,
370  G_PARAM_READWRITE));
371 
372  g_object_class_install_property
373  (gobject_class,
374  PROP_BILLTERMS,
375  g_param_spec_object ("terms",
376  "Terms",
377  "The billing terms used by this vendor.",
378  GNC_TYPE_BILLTERM,
379  G_PARAM_READWRITE));
380 
381  g_object_class_install_property
382  (gobject_class,
383  PROP_TAXTABLE,
384  g_param_spec_object ("tax-table",
385  "Tax table",
386  "The tax table which applies to this vendor.",
387  GNC_TYPE_TAXTABLE,
388  G_PARAM_READWRITE));
389 
390  g_object_class_install_property
391  (gobject_class,
392  PROP_ADDRESS,
393  g_param_spec_object ("address",
394  "Address",
395  "The address property contains the address information for this vendor.",
396  GNC_TYPE_ADDRESS,
397  G_PARAM_READWRITE));
398 
399  g_object_class_install_property
400  (gobject_class,
401  PROP_TAX_INCLUDED,
402  g_param_spec_int ("tax-included",
403  "Tax included",
404  "The tax-included property contains the information about tax calculation this vendor.",
405  GNC_TAXINCLUDED_YES, /* min */
406  GNC_TAXINCLUDED_USEGLOBAL, /* max */
407  GNC_TAXINCLUDED_USEGLOBAL, /* default */
408  G_PARAM_READWRITE));
409 
410  g_object_class_install_property
411  (gobject_class,
412  PROP_TAX_INCLUDED_STR,
413  g_param_spec_string("tax-included-string",
414  "Tax included string",
415  "The tax-included-string property contains a character version of tax-included.",
416  FALSE,
417  G_PARAM_READWRITE));
418  g_object_class_install_property
419  (gobject_class,
420  PROP_PDF_DIRNAME,
421  g_param_spec_string ("export-pdf-dir",
422  "Export PDF Directory Name",
423  "A subdirectory for exporting PDF reports which is "
424  "appended to the target directory when writing them "
425  "out. It is retrieved from preferences and stored on "
426  "each 'Owner' object which prints items after "
427  "printing.",
428  NULL,
429  G_PARAM_READWRITE));
430 
431  g_object_class_install_property(
432  gobject_class,
433  PROP_LAST_POSTED,
434  g_param_spec_boxed("invoice-last-posted-account",
435  "Invoice Last Posted Account",
436  "The last account to which an invoice belonging to "
437  "this owner was posted.",
438  GNC_TYPE_GUID,
439  G_PARAM_READWRITE));
440 
441  g_object_class_install_property(
442  gobject_class,
443  PROP_PAYMENT_LAST_ACCT,
444  g_param_spec_boxed("payment-last-account",
445  "Payment Last Account",
446  "The last account to which an payment belonging to "
447  "this owner was posted.",
448  GNC_TYPE_GUID,
449  G_PARAM_READWRITE));
450 }
451 
452 /* Create/Destroy Functions */
453 GncVendor *gncVendorCreate (QofBook *book)
454 {
455  GncVendor *vendor;
456 
457  if (!book) return NULL;
458 
459  vendor = g_object_new (GNC_TYPE_VENDOR, NULL);
460  qof_instance_init_data (&vendor->inst, _GNC_MOD_NAME, book);
461 
462  vendor->id = CACHE_INSERT ("");
463  vendor->name = CACHE_INSERT ("");
464  vendor->notes = CACHE_INSERT ("");
465  vendor->addr = gncAddressCreate (book, &vendor->inst);
466  vendor->taxincluded = GNC_TAXINCLUDED_USEGLOBAL;
467  vendor->active = TRUE;
468  vendor->jobs = NULL;
469  vendor->balance = NULL;
470 
471  if (vend_qof_event_handler_id == 0)
472  vend_qof_event_handler_id = qof_event_register_handler (vend_handle_qof_events, NULL);
473 
474  qof_event_gen (&vendor->inst, QOF_EVENT_CREATE, NULL);
475 
476  return vendor;
477 }
478 
479 void gncVendorDestroy (GncVendor *vendor)
480 {
481  if (!vendor) return;
482  qof_instance_set_destroying(vendor, TRUE);
483  gncVendorCommitEdit (vendor);
484 }
485 
486 static void gncVendorFree (GncVendor *vendor)
487 {
488  if (!vendor) return;
489 
490  qof_event_gen (&vendor->inst, QOF_EVENT_DESTROY, NULL);
491 
492  CACHE_REMOVE (vendor->id);
493  CACHE_REMOVE (vendor->name);
494  CACHE_REMOVE (vendor->notes);
495  gncAddressBeginEdit (vendor->addr);
496  gncAddressDestroy (vendor->addr);
497 
498  gncJobFreeList (vendor->jobs);
499  g_list_free (vendor->jobs);
500  g_free (vendor->balance);
501 
502  if (!qof_book_shutting_down (qof_instance_get_book (QOF_INSTANCE(vendor))))
503  {
504  if (vendor->terms)
505  gncBillTermDecRef (vendor->terms);
506  if (vendor->taxtable)
507  gncTaxTableDecRef (vendor->taxtable);
508  }
509 
510  /* qof_instance_release (&vendor->inst); */
511  g_object_unref (vendor);
512 }
513 
514 /* ============================================================== */
515 /* Set Functions */
516 
517 #define SET_STR(obj, member, str) { \
518  if (!g_strcmp0 (member, str)) return; \
519  gncVendorBeginEdit (obj); \
520  CACHE_REPLACE (member, str); \
521  }
522 
523 void gncVendorSetID (GncVendor *vendor, const char *id)
524 {
525  if (!vendor) return;
526  if (!id) return;
527  SET_STR(vendor, vendor->id, id);
528  mark_vendor (vendor);
529  gncVendorCommitEdit (vendor);
530 }
531 
532 void gncVendorSetName (GncVendor *vendor, const char *name)
533 {
534  if (!vendor) return;
535  if (!name) return;
536  SET_STR(vendor, vendor->name, name);
537  mark_vendor (vendor);
538  gncVendorCommitEdit (vendor);
539 }
540 
541 void gncVendorSetNotes (GncVendor *vendor, const char *notes)
542 {
543  if (!vendor) return;
544  if (!notes) return;
545  SET_STR(vendor, vendor->notes, notes);
546  mark_vendor (vendor);
547  gncVendorCommitEdit (vendor);
548 }
549 
550 void gncVendorSetTerms (GncVendor *vendor, GncBillTerm *terms)
551 {
552  if (!vendor) return;
553  if (vendor->terms == terms) return;
554 
555  gncVendorBeginEdit (vendor);
556  if (vendor->terms)
557  gncBillTermDecRef (vendor->terms);
558  vendor->terms = terms;
559  if (vendor->terms)
560  gncBillTermIncRef (vendor->terms);
561  mark_vendor (vendor);
562  gncVendorCommitEdit (vendor);
563 }
564 
565 void gncVendorSetTaxIncluded (GncVendor *vendor, GncTaxIncluded taxincl)
566 {
567  if (!vendor) return;
568  if (taxincl == vendor->taxincluded) return;
569  gncVendorBeginEdit (vendor);
570  vendor->taxincluded = taxincl;
571  mark_vendor (vendor);
572  gncVendorCommitEdit (vendor);
573 }
574 
575 void gncVendorSetCurrency (GncVendor *vendor, gnc_commodity *currency)
576 {
577  if (!vendor || !currency) return;
578  if (vendor->currency &&
579  gnc_commodity_equal (vendor->currency, currency))
580  return;
581  gncVendorBeginEdit (vendor);
582  vendor->currency = currency;
583  mark_vendor (vendor);
584  gncVendorCommitEdit (vendor);
585 }
586 
587 void gncVendorSetActive (GncVendor *vendor, gboolean active)
588 {
589  if (!vendor) return;
590  if (active == vendor->active) return;
591  gncVendorBeginEdit (vendor);
592  vendor->active = active;
593  mark_vendor (vendor);
594  gncVendorCommitEdit (vendor);
595 }
596 
597 void gncVendorSetTaxTableOverride (GncVendor *vendor, gboolean override)
598 {
599  if (!vendor) return;
600  if (vendor->taxtable_override == override) return;
601  gncVendorBeginEdit (vendor);
602  vendor->taxtable_override = override;
603  mark_vendor (vendor);
604  gncVendorCommitEdit (vendor);
605 }
606 
607 void gncVendorSetTaxTable (GncVendor *vendor, GncTaxTable *table)
608 {
609  if (!vendor) return;
610  if (vendor->taxtable == table) return;
611  gncVendorBeginEdit (vendor);
612  if (vendor->taxtable)
613  gncTaxTableDecRef (vendor->taxtable);
614  if (table)
615  gncTaxTableIncRef (table);
616  vendor->taxtable = table;
617  mark_vendor (vendor);
618  gncVendorCommitEdit (vendor);
619 }
620 
621 static void
622 qofVendorSetAddr (GncVendor *vendor, QofInstance *addr_ent)
623 {
624  GncAddress *addr;
625 
626  if (!vendor || !addr_ent)
627  {
628  return;
629  }
630  addr = (GncAddress*)addr_ent;
631  if (addr == vendor->addr)
632  {
633  return;
634  }
635  if (vendor->addr != NULL)
636  {
637  gncAddressBeginEdit(vendor->addr);
638  gncAddressDestroy(vendor->addr);
639  }
640  gncVendorBeginEdit(vendor);
641  vendor->addr = addr;
642  gncVendorCommitEdit(vendor);
643 }
644 
645 static void
646 qofVendorSetTaxIncluded(GncVendor *vendor, const char* type_string)
647 {
648  GncTaxIncluded inc;
649 
650  if (!gncTaxIncludedStringToType(type_string, &inc))
651  {
652  return;
653  }
654  gncVendorBeginEdit(vendor);
655  vendor->taxincluded = inc;
656  gncVendorCommitEdit(vendor);
657 }
658 
659 /* ============================================================== */
660 /* Get Functions */
661 
662 const char * gncVendorGetID (const GncVendor *vendor)
663 {
664  if (!vendor) return NULL;
665  return vendor->id;
666 }
667 
668 const char * gncVendorGetName (const GncVendor *vendor)
669 {
670  if (!vendor) return NULL;
671  return vendor->name;
672 }
673 
674 GncAddress * gncVendorGetAddr (const GncVendor *vendor)
675 {
676  if (!vendor) return NULL;
677  return vendor->addr;
678 }
679 
680 const char * gncVendorGetNotes (const GncVendor *vendor)
681 {
682  if (!vendor) return NULL;
683  return vendor->notes;
684 }
685 
686 GncBillTerm * gncVendorGetTerms (const GncVendor *vendor)
687 {
688  if (!vendor) return 0;
689  return vendor->terms;
690 }
691 
692 GncTaxIncluded gncVendorGetTaxIncluded (const GncVendor *vendor)
693 {
694  if (!vendor) return GNC_TAXINCLUDED_USEGLOBAL;
695  return vendor->taxincluded;
696 }
697 
698 gnc_commodity * gncVendorGetCurrency (const GncVendor *vendor)
699 {
700  if (!vendor) return NULL;
701  return vendor->currency;
702 }
703 
704 gboolean gncVendorGetActive (const GncVendor *vendor)
705 {
706  if (!vendor) return FALSE;
707  return vendor->active;
708 }
709 
710 gboolean gncVendorGetTaxTableOverride (const GncVendor *vendor)
711 {
712  if (!vendor) return FALSE;
713  return vendor->taxtable_override;
714 }
715 
716 GncTaxTable* gncVendorGetTaxTable (const GncVendor *vendor)
717 {
718  if (!vendor) return NULL;
719  return vendor->taxtable;
720 }
721 
722 static const char*
723 qofVendorGetTaxIncluded(const GncVendor *vendor)
724 {
725  return gncTaxIncludedTypeToString(vendor->taxincluded);
726 }
727 
728 /* Note that JobList changes do not affect the "dirtiness" of the vendor */
729 void gncVendorAddJob (GncVendor *vendor, GncJob *job)
730 {
731  if (!vendor) return;
732  if (!job) return;
733 
734  if (g_list_index(vendor->jobs, job) == -1)
735  vendor->jobs = g_list_insert_sorted (vendor->jobs, job,
736  (GCompareFunc)gncJobCompare);
737 
738  qof_event_gen (&vendor->inst, QOF_EVENT_MODIFY, NULL);
739 }
740 
741 void gncVendorRemoveJob (GncVendor *vendor, GncJob *job)
742 {
743  GList *node;
744 
745  if (!vendor) return;
746  if (!job) return;
747 
748  node = g_list_find (vendor->jobs, job);
749  if (!node)
750  {
751  /* PERR ("split not in account"); */
752  }
753  else
754  {
755  vendor->jobs = g_list_remove_link (vendor->jobs, node);
756  g_list_free_1 (node);
757  }
758 
759  qof_event_gen (&vendor->inst, QOF_EVENT_MODIFY, NULL);
760 }
761 
762 void gncVendorBeginEdit (GncVendor *vendor)
763 {
764  qof_begin_edit(&vendor->inst);
765 }
766 
767 static void gncVendorOnError (QofInstance *vendor, QofBackendError errcode)
768 {
769  PERR("Vendor QofBackend Failure: %d", errcode);
770  gnc_engine_signal_commit_error( errcode );
771 }
772 
773 static void gncVendorOnDone (QofInstance *inst)
774 {
775  GncVendor *vendor = (GncVendor *) inst;
776  gncAddressClearDirty (vendor->addr);
777 }
778 
779 static void vendor_free (QofInstance *inst)
780 {
781  GncVendor *vendor = (GncVendor *) inst;
782  gncVendorFree (vendor);
783 }
784 
785 void gncVendorCommitEdit (GncVendor *vendor)
786 {
787  if (!qof_commit_edit (QOF_INSTANCE(vendor))) return;
788  qof_commit_edit_part2 (&vendor->inst, gncVendorOnError,
789  gncVendorOnDone, vendor_free);
790 }
791 
792 /* ============================================================== */
793 /* Other functions */
794 
795 int gncVendorCompare (const GncVendor *a, const GncVendor *b)
796 {
797  if (!a && !b) return 0;
798  if (!a && b) return 1;
799  if (a && !b) return -1;
800 
801  return(strcmp(a->name, b->name));
802 }
803 
804 gboolean gncVendorEqual(const GncVendor *a, const GncVendor *b)
805 {
806  if (a == NULL && b == NULL) return TRUE;
807  if (a == NULL || b == NULL) return FALSE;
808 
809  g_return_val_if_fail(GNC_IS_VENDOR(a), FALSE);
810  g_return_val_if_fail(GNC_IS_VENDOR(b), FALSE);
811 
812  if (g_strcmp0(a->id, b->id) != 0)
813  {
814  PWARN("IDs differ: %s vs %s", a->id, b->id);
815  return FALSE;
816  }
817 
818  if (g_strcmp0(a->name, b->name) != 0)
819  {
820  PWARN("Names differ: %s vs %s", a->name, b->name);
821  return FALSE;
822  }
823 
824  if (g_strcmp0(a->notes, b->notes) != 0)
825  {
826  PWARN("Notes differ");
827  return FALSE;
828  }
829 
830  if (!gncBillTermEqual(a->terms, b->terms))
831  {
832  PWARN("BillTerms differ");
833  return FALSE;
834  }
835 
836  if (!gncAddressEqual(a->addr, b->addr))
837  {
838  PWARN("Addresses differ");
839  return FALSE;
840  }
841 
842  if (!gnc_commodity_equal(a->currency, b->currency))
843  {
844  PWARN("Currencies differ");
845  return FALSE;
846  }
847 
848  if (!gncTaxTableEqual(a->taxtable, b->taxtable))
849  {
850  PWARN("Tax tables differ");
851  return FALSE;
852  }
853 
854  if (a->taxtable_override != b->taxtable_override)
855  {
856  PWARN("Tax table override flags differ");
857  return FALSE;
858  }
859 
860  if (a->taxincluded != b->taxincluded)
861  {
862  PWARN("Tax included flags differ");
863  return FALSE;
864  }
865 
866  if (a->active != b->active)
867  {
868  PWARN("Active flags differ");
869  return FALSE;
870  }
871 
872 // GList * jobs;
873  return TRUE;
874 }
875 
876 gboolean
877 gncVendorIsDirty (const GncVendor *vendor)
878 {
879  if (!vendor) return FALSE;
880  return (qof_instance_get_dirty_flag(vendor)
881  || gncAddressIsDirty (vendor->addr));
882 }
883 
896 static void
897 vend_handle_qof_events (QofInstance *entity, QofEventId event_type,
898  gpointer user_data, gpointer event_data)
899 {
900  /* Handle address change events */
901  if ((GNC_IS_ADDRESS (entity) &&
902  (event_type & QOF_EVENT_MODIFY) != 0))
903  {
904  if (GNC_IS_VENDOR (event_data))
905  {
906  GncVendor* vend = GNC_VENDOR (event_data);
907  gncVendorBeginEdit (vend);
908  mark_vendor (vend);
909  gncVendorCommitEdit (vend);
910  }
911  return;
912  }
913 
914  /* Handle lot change events */
915  if (GNC_IS_LOT (entity))
916  {
917  GNCLot *lot = GNC_LOT (entity);
918  GncOwner lot_owner;
919  const GncOwner *end_owner = NULL;
920  GncInvoice *invoice = gncInvoiceGetInvoiceFromLot (lot);
921 
922  /* Determine the owner associated with the lot */
923  if (invoice)
924  /* Invoice lots */
925  end_owner = gncOwnerGetEndOwner (gncInvoiceGetOwner (invoice));
926  else if (gncOwnerGetOwnerFromLot (lot, &lot_owner))
927  /* Pre-payment lots */
928  end_owner = gncOwnerGetEndOwner (&lot_owner);
929 
930  if (gncOwnerGetType (end_owner) == GNC_OWNER_VENDOR)
931  {
932  /* Clear the cached balance */
933  GncVendor* vend = gncOwnerGetVendor (end_owner);
934  g_free (vend->balance);
935  vend->balance = NULL;
936  }
937  return;
938  }
939 }
940 
941 /* ============================================================== */
942 /* Package-Private functions */
943 
944 static const char * _gncVendorPrintable (gpointer item)
945 {
946  GncVendor *v = item;
947  if (!item) return NULL;
948  return v->name;
949 }
950 
951 static void
952 destroy_vendor_on_book_close(QofInstance *ent, gpointer data)
953 {
954  GncVendor* v = GNC_VENDOR(ent);
955 
956  gncVendorBeginEdit(v);
957  gncVendorDestroy(v);
958 }
959 
964 static void
965 gnc_vendor_book_end(QofBook* book)
966 {
967  QofCollection *col;
968 
969  col = qof_book_get_collection(book, GNC_ID_VENDOR);
970  qof_collection_foreach(col, destroy_vendor_on_book_close, NULL);
971 }
972 
973 static QofObject gncVendorDesc =
974 {
975  DI(.interface_version = ) QOF_OBJECT_VERSION,
976  DI(.e_type = ) _GNC_MOD_NAME,
977  DI(.type_label = ) "Vendor",
978  DI(.create = ) (gpointer)gncVendorCreate,
979  DI(.book_begin = ) NULL,
980  DI(.book_end = ) gnc_vendor_book_end,
981  DI(.is_dirty = ) qof_collection_is_dirty,
982  DI(.mark_clean = ) qof_collection_mark_clean,
983  DI(.foreach = ) qof_collection_foreach,
984  DI(.printable = ) _gncVendorPrintable,
985  DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
986 };
987 
988 gboolean gncVendorRegister (void)
989 {
990  static QofParam params[] =
991  {
992  { VENDOR_ID, QOF_TYPE_STRING, (QofAccessFunc)gncVendorGetID, (QofSetterFunc)gncVendorSetID },
993  { VENDOR_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncVendorGetName, (QofSetterFunc)gncVendorSetName },
994  { VENDOR_ADDR, GNC_ID_ADDRESS, (QofAccessFunc)gncVendorGetAddr, (QofSetterFunc)qofVendorSetAddr },
995  { VENDOR_NOTES, QOF_TYPE_STRING, (QofAccessFunc)gncVendorGetNotes, (QofSetterFunc)gncVendorSetNotes },
996  { VENDOR_TERMS, GNC_ID_BILLTERM, (QofAccessFunc)gncVendorGetTerms, (QofSetterFunc)gncVendorSetTerms },
997  {
998  VENDOR_TAX_OVERRIDE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncVendorGetTaxTableOverride,
999  (QofSetterFunc)gncVendorSetTaxTableOverride
1000  },
1001  {
1002  VENDOR_TAX_TABLE, GNC_ID_TAXTABLE, (QofAccessFunc)gncVendorGetTaxTable,
1003  (QofSetterFunc)gncVendorSetTaxTable
1004  },
1005  {
1006  VENDOR_TAX_INC, QOF_TYPE_STRING, (QofAccessFunc)qofVendorGetTaxIncluded,
1007  (QofSetterFunc)qofVendorSetTaxIncluded
1008  },
1009  { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
1010  { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
1011  { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncVendorGetActive, NULL },
1012  { NULL },
1013  };
1014 
1015  qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncVendorCompare, params);
1016 
1017  return qof_object_register (&gncVendorDesc);
1018 }
1019 
1020 gchar *gncVendorNextID (QofBook *book)
1021 {
1022  return qof_book_increment_and_format_counter (book, _GNC_MOD_NAME);
1023 }
1024 
1025 const gnc_numeric*
1026 gncVendorGetCachedBalance (GncVendor *vend)
1027 {
1028  return vend->balance;
1029 }
1030 
1031 void gncVendorSetCachedBalance (GncVendor *vend, const gnc_numeric *new_bal)
1032 {
1033  if (!new_bal)
1034  {
1035  if (vend->balance)
1036  {
1037  g_free (vend->balance);
1038  vend->balance = NULL;
1039  }
1040  return;
1041  }
1042 
1043  if (!vend->balance)
1044  vend->balance = g_new0 (gnc_numeric, 1);
1045 
1046  *vend->balance = *new_bal;
1047 }
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
Compare two instances, based on their last update times.
const GncGUID * qof_instance_get_guid(gconstpointer inst)
Return the GncGUID of this instance.
void qof_instance_set_kvp(QofInstance *, GValue const *value, unsigned count,...)
Sets a KVP slot to a value from a GValue.
QofBook * qof_instance_get_book(gconstpointer inst)
Return the book pointer.
gboolean qof_collection_is_dirty(const QofCollection *col)
Return value of &#39;dirty&#39; flag on collection.
Definition: qofid.cpp:255
GncTaxIncluded
How to interpret the TaxIncluded.
Definition: gncTaxTable.h:85
QofBackendError
The errors that can be reported to the GUI & other front-end users.
Definition: qofbackend.h:57
gchar * qof_book_increment_and_format_counter(QofBook *book, const char *counter_name)
This will increment the named counter for this book and format it.
Definition: qofbook.cpp:625
GList * qof_instance_get_referring_object_list_from_collection(const QofCollection *coll, const QofInstance *ref)
Returns a list of objects from the collection which refer to the specific object. ...
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
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equal.
tax is included
Definition: gncTaxTable.h:87
QofCollection * qof_instance_get_collection(gconstpointer ptr)
Return the collection this instance belongs to.
int(* QofSortFunc)(gconstpointer, gconstpointer)
This function is the default sort function for a particular object type.
Definition: qofclass.h:223
#define QOF_OBJECT_VERSION
Defines the version of the core object object registration interface.
Definition: qofobject.h:63
gboolean qof_commit_edit(QofInstance *inst)
commit_edit helpers
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
#define QOF_PARAM_BOOK
"Known" Object Parameters – all objects must support these
Definition: qofquery.h:108
use the global setting
Definition: gncTaxTable.h:89
void(* QofSetterFunc)(gpointer, gpointer)
The QofSetterFunc defines an function pointer for parameter setters.
Definition: qofclass.h:185
void qof_instance_get_kvp(QofInstance *, GValue *value, unsigned count,...)
Retrieves the contents of a KVP slot into a provided GValue.
gboolean gncBillTermEqual(const GncBillTerm *a, const GncBillTerm *b)
Check if all internal fields of a and b match.
Definition: gncBillTerm.c:643
gint qof_event_register_handler(QofEventHandler handler, gpointer user_data)
Register a handler for events.
Definition: qofevent.cpp:73
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
void qof_instance_init_data(QofInstance *inst, QofIdType type, QofBook *book)
Initialise the settings associated with an instance.
gboolean qof_begin_edit(QofInstance *inst)
begin_edit
gint QofEventId
Define the type of events allowed.
Definition: qofevent.h:45
gboolean qof_instance_get_dirty_flag(gconstpointer ptr)
Retrieve the flag that indicates whether or not this object has been modified.
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 gncOwnerGetOwnerFromLot(GNCLot *lot, GncOwner *owner)
Get the owner from the lot.
Definition: gncOwner.c:636
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
The QofAccessFunc defines an arbitrary function pointer for access functions.
Definition: qofclass.h:178
void qof_collection_mark_clean(QofCollection *)
reset value of dirty flag
Definition: qofid.cpp:261
int gncVendorCompare(const GncVendor *a, const GncVendor *b)
XXX should be renamed to RetJobList to be consistent with other usage, since caller must free the cop...
Definition: gncVendor.c:795
gboolean gncAddressEqual(const GncAddress *a, const GncAddress *b)
Deeply compare two addresses.
Definition: gncAddress.c:577
GncOwnerType gncOwnerGetType(const GncOwner *owner)
Returns the GncOwnerType of this owner.
Definition: gncOwner.c:200
const GncOwner * gncOwnerGetEndOwner(const GncOwner *owner)
Get the "parent" Owner or GncGUID thereof.
Definition: gncOwner.c:572
GncInvoice * gncInvoiceGetInvoiceFromLot(GNCLot *lot)
Given a LOT, find and return the Invoice attached to the lot.
Definition: gncInvoice.c:1289
Business Invoice Interface.
gboolean gncVendorEqual(const GncVendor *a, const GncVendor *b)
Test support function, used by test-dbi-business-stuff.c.
Definition: gncVendor.c:804
GncVendor * gncOwnerGetVendor(const GncOwner *owner)
If the given owner is of type GNC_OWNER_VENDOR, returns the pointer to the vendor object...
Definition: gncOwner.c:383
Vendor Interface.
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
Definition: qofbook.cpp:521
gboolean qof_object_register(const QofObject *object)
Register new types of object objects.
Definition: qofobject.cpp:299
gboolean qof_book_shutting_down(const QofBook *book)
Is the book shutting down?
Definition: qofbook.cpp:447
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
Commodity handling public routines.
modtime is the internal date of the last modtime See libgnucash/engine/TaxTableBillTermImmutability.txt for an explanation of the following Code that handles refcount, parent, child, invisible and children is identical to that in ::GncBillTerm