GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gncCustomer.c
1 /********************************************************************\
2  * gncCustomer.c -- the Core Customer 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 [email protected] *
20  * *
21 \********************************************************************/
22 
23 /*
24  * Copyright (C) 2001,2002 Derek Atkins
25  * Copyright (C) 2003 Linas Vepstas <[email protected]>
26  * Author: Derek Atkins <[email protected]>
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 
37 #include "gncAddressP.h"
38 #include "gncBillTermP.h"
39 #include "gncInvoice.h"
40 #ifdef GNUCASH_MAJOR_VERSION
41 #include "gncBusiness.h"
42 #endif
43 
44 #include "gncCustomer.h"
45 #include "gncCustomerP.h"
46 #include "gncJobP.h"
47 #include "gncTaxTableP.h"
48 
49 static gint gs_address_event_handler_id = 0;
50 static void listen_for_address_events(QofInstance *entity, QofEventId event_type,
51  gpointer user_data, gpointer event_data);
52 
54 {
55  QofInstance inst;
56 
57  /* The following fields are identical to 'vendor' */
58  char * id;
59  char * name;
60  char * notes;
61  GncBillTerm * terms;
62  GncAddress * addr;
63  gnc_commodity * currency;
64  GncTaxTable* taxtable;
65  gboolean taxtable_override;
66  GncTaxIncluded taxincluded;
67  gboolean active;
68  GList * jobs;
69 
70  /* The following fields are unique to 'customer' */
71  gnc_numeric credit;
72  gnc_numeric discount;
73  GncAddress * shipaddr;
74 };
75 
77 {
78  QofInstanceClass parent_class;
79 };
80 
81 static QofLogModule log_module = GNC_MOD_BUSINESS;
82 
83 #define _GNC_MOD_NAME GNC_ID_CUSTOMER
84 
85 /* ============================================================== */
86 /* misc inline funcs */
87 
88 G_INLINE_FUNC void mark_customer (GncCustomer *customer);
89 void mark_customer (GncCustomer *customer)
90 {
91  qof_instance_set_dirty(&customer->inst);
92  qof_event_gen (&customer->inst, QOF_EVENT_MODIFY, NULL);
93 }
94 
95 /* ============================================================== */
96 
97 enum
98 {
99  PROP_0,
100  PROP_NAME,
101  PROP_PDF_DIRNAME,
102  PROP_LAST_POSTED,
103  PROP_PAYMENT_LAST_ACCT,
104 };
105 
106 /* GObject Initialization */
107 G_DEFINE_TYPE(GncCustomer, gnc_customer, QOF_TYPE_INSTANCE);
108 
109 static void
110 gnc_customer_init(GncCustomer* cust)
111 {
112 }
113 
114 static void
115 gnc_customer_dispose(GObject *custp)
116 {
117  G_OBJECT_CLASS(gnc_customer_parent_class)->dispose(custp);
118 }
119 
120 static void
121 gnc_customer_finalize(GObject* custp)
122 {
123  G_OBJECT_CLASS(gnc_customer_parent_class)->finalize(custp);
124 }
125 
126 static void
127 gnc_customer_get_property (GObject *object,
128  guint prop_id,
129  GValue *value,
130  GParamSpec *pspec)
131 {
132  GncCustomer *cust;
133  gchar *key;
134  g_return_if_fail(GNC_IS_CUSTOMER(object));
135 
136  cust = GNC_CUSTOMER(object);
137  switch (prop_id)
138  {
139  case PROP_NAME:
140  g_value_set_string(value, cust->name);
141  break;
142  case PROP_PDF_DIRNAME:
143  key = OWNER_EXPORT_PDF_DIRNAME;
144  qof_instance_get_kvp (QOF_INSTANCE (cust), key, value);
145  break;
146  case PROP_LAST_POSTED:
147  key = LAST_POSTED_TO_ACCT;
148  qof_instance_get_kvp (QOF_INSTANCE (cust), key, value);
149  break;
150  case PROP_PAYMENT_LAST_ACCT:
151  key = GNC_PAYMENT "/" GNC_LAST_ACCOUNT;
152  qof_instance_get_kvp (QOF_INSTANCE (cust), key, value);
153  break;
154  default:
155  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
156  break;
157  }
158 }
159 
160 static void
161 gnc_customer_set_property (GObject *object,
162  guint prop_id,
163  const GValue *value,
164  GParamSpec *pspec)
165 {
166  GncCustomer *cust;
167  gchar *key;
168 
169  g_return_if_fail(GNC_IS_CUSTOMER(object));
170 
171  cust = GNC_CUSTOMER(object);
172  g_assert (qof_instance_get_editlevel(cust));
173 
174  switch (prop_id)
175  {
176  case PROP_NAME:
177  gncCustomerSetName(cust, g_value_get_string(value));
178  break;
179  case PROP_PDF_DIRNAME:
180  key = OWNER_EXPORT_PDF_DIRNAME;
181  qof_instance_set_kvp (QOF_INSTANCE (cust), key, value);
182  break;
183  case PROP_LAST_POSTED:
184  key = LAST_POSTED_TO_ACCT;
185  qof_instance_set_kvp (QOF_INSTANCE (cust), key, value);
186  break;
187  case PROP_PAYMENT_LAST_ACCT:
188  key = GNC_PAYMENT "/" GNC_LAST_ACCOUNT;
189  qof_instance_set_kvp (QOF_INSTANCE (cust), key, value);
190  break;
191  default:
192  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
193  break;
194  }
195 }
196 
198 static gchar*
199 impl_get_display_name(const QofInstance* inst)
200 {
201  GncCustomer* cust;
202 
203  g_return_val_if_fail(inst != NULL, FALSE);
204  g_return_val_if_fail(GNC_IS_CUSTOMER(inst), FALSE);
205 
206  cust = GNC_CUSTOMER(inst);
207  /* XXX internationalization of "Customer" */
208  return g_strdup_printf("Customer %s", cust->name);
209 }
210 
212 static gboolean
213 impl_refers_to_object(const QofInstance* inst, const QofInstance* ref)
214 {
215  GncCustomer* cust;
216 
217  g_return_val_if_fail(inst != NULL, FALSE);
218  g_return_val_if_fail(GNC_IS_CUSTOMER(inst), FALSE);
219 
220  cust = GNC_CUSTOMER(inst);
221 
222  if (GNC_IS_BILLTERM(ref))
223  {
224  return (cust->terms == GNC_BILLTERM(ref));
225  }
226  else if (GNC_IS_TAXTABLE(ref))
227  {
228  return (cust->taxtable == GNC_TAXTABLE(ref));
229  }
230 
231  return FALSE;
232 }
233 
240 static GList*
241 impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
242 {
243  if (!GNC_IS_BILLTERM(ref) && !GNC_IS_TAXTABLE(ref))
244  {
245  return NULL;
246  }
247 
249 }
250 
251 static void
252 gnc_customer_class_init (GncCustomerClass *klass)
253 {
254  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
255  QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
256 
257  gobject_class->dispose = gnc_customer_dispose;
258  gobject_class->finalize = gnc_customer_finalize;
259  gobject_class->set_property = gnc_customer_set_property;
260  gobject_class->get_property = gnc_customer_get_property;
261 
262  qof_class->get_display_name = impl_get_display_name;
263  qof_class->refers_to_object = impl_refers_to_object;
264  qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
265 
266  g_object_class_install_property
267  (gobject_class,
268  PROP_NAME,
269  g_param_spec_string ("name",
270  "Customer Name",
271  "The customer is an arbitrary string "
272  "assigned by the user which provides the "
273  "customer name.",
274  NULL,
275  G_PARAM_READWRITE));
276 
277  g_object_class_install_property
278  (gobject_class,
279  PROP_PDF_DIRNAME,
280  g_param_spec_string ("export-pdf-dir",
281  "Export PDF Directory Name",
282  "A subdirectory for exporting PDF reports which is "
283  "appended to the target directory when writing them "
284  "out. It is retrieved from preferences and stored on "
285  "each 'Owner' object which prints items after "
286  "printing.",
287  NULL,
288  G_PARAM_READWRITE));
289 
290  g_object_class_install_property(
291  gobject_class,
292  PROP_LAST_POSTED,
293  g_param_spec_boxed("invoice-last-posted-account",
294  "Invoice Last Posted Account",
295  "The last account to which an invoice belonging to "
296  "this owner was posted.",
297  GNC_TYPE_GUID,
298  G_PARAM_READWRITE));
299 
300  g_object_class_install_property(
301  gobject_class,
302  PROP_PAYMENT_LAST_ACCT,
303  g_param_spec_boxed("payment-last-account",
304  "Payment Last Account",
305  "The last account to which an payment belonging to "
306  "this owner was posted.",
307  GNC_TYPE_GUID,
308  G_PARAM_READWRITE));
309 }
310 
311 /* Create/Destroy Functions */
312 GncCustomer *gncCustomerCreate (QofBook *book)
313 {
314  GncCustomer *cust;
315 
316  if (!book) return NULL;
317 
318  cust = g_object_new (GNC_TYPE_CUSTOMER, NULL);
319  qof_instance_init_data (&cust->inst, _GNC_MOD_NAME, book);
320 
321  cust->id = CACHE_INSERT ("");
322  cust->name = CACHE_INSERT ("");
323  cust->notes = CACHE_INSERT ("");
324  cust->addr = gncAddressCreate (book, &cust->inst);
325  cust->taxincluded = GNC_TAXINCLUDED_USEGLOBAL;
326  cust->active = TRUE;
327  cust->jobs = NULL;
328 
329  cust->discount = gnc_numeric_zero();
330  cust->credit = gnc_numeric_zero();
331  cust->shipaddr = gncAddressCreate (book, &cust->inst);
332 
333  if (gs_address_event_handler_id == 0)
334  {
335  gs_address_event_handler_id = qof_event_register_handler(listen_for_address_events, NULL);
336  }
337 
338  qof_event_gen (&cust->inst, QOF_EVENT_CREATE, NULL);
339 
340  return cust;
341 }
342 
343 void gncCustomerDestroy (GncCustomer *cust)
344 {
345  if (!cust) return;
346  qof_instance_set_destroying(cust, TRUE);
347  qof_instance_set_dirty (&cust->inst);
348  gncCustomerCommitEdit (cust);
349 }
350 
351 static void gncCustomerFree (GncCustomer *cust)
352 {
353  if (!cust) return;
354 
355  qof_event_gen (&cust->inst, QOF_EVENT_DESTROY, NULL);
356 
357  CACHE_REMOVE (cust->id);
358  CACHE_REMOVE (cust->name);
359  CACHE_REMOVE (cust->notes);
360  gncAddressBeginEdit (cust->addr);
361  gncAddressDestroy (cust->addr);
362  gncAddressBeginEdit (cust->shipaddr);
363  gncAddressDestroy (cust->shipaddr);
364  g_list_free (cust->jobs);
365 
366  if (cust->terms)
367  gncBillTermDecRef (cust->terms);
368  if (cust->taxtable)
369  {
370  gncTaxTableDecRef (cust->taxtable);
371  }
372 
373  /* qof_instance_release (&cust->inst); */
374  g_object_unref (cust);
375 }
376 
377 /* ============================================================== */
378 /* Set Functions */
379 
380 #define SET_STR(obj, member, str) { \
381  char * tmp; \
382  \
383  if (!g_strcmp0 (member, str)) return; \
384  gncCustomerBeginEdit (obj); \
385  tmp = CACHE_INSERT (str); \
386  CACHE_REMOVE (member); \
387  member = tmp; \
388  }
389 
390 void gncCustomerSetID (GncCustomer *cust, const char *id)
391 {
392  if (!cust) return;
393  if (!id) return;
394  SET_STR(cust, cust->id, id);
395  mark_customer (cust);
396  gncCustomerCommitEdit (cust);
397 }
398 
399 void gncCustomerSetName (GncCustomer *cust, const char *name)
400 {
401  if (!cust) return;
402  if (!name) return;
403  SET_STR(cust, cust->name, name);
404  mark_customer (cust);
405  gncCustomerCommitEdit (cust);
406 }
407 
408 void gncCustomerSetNotes (GncCustomer *cust, const char *notes)
409 {
410  if (!cust) return;
411  if (!notes) return;
412  SET_STR(cust, cust->notes, notes);
413  mark_customer (cust);
414  gncCustomerCommitEdit (cust);
415 }
416 
417 void gncCustomerSetTerms (GncCustomer *cust, GncBillTerm *terms)
418 {
419  if (!cust) return;
420  if (cust->terms == terms) return;
421 
422  gncCustomerBeginEdit (cust);
423  if (cust->terms)
424  gncBillTermDecRef (cust->terms);
425  cust->terms = terms;
426  if (cust->terms)
427  gncBillTermIncRef (cust->terms);
428  mark_customer (cust);
429  gncCustomerCommitEdit (cust);
430 }
431 
432 void gncCustomerSetTaxIncluded (GncCustomer *cust, GncTaxIncluded taxincl)
433 {
434  if (!cust) return;
435  if (taxincl == cust->taxincluded) return;
436  gncCustomerBeginEdit (cust);
437  cust->taxincluded = taxincl;
438  mark_customer (cust);
439  gncCustomerCommitEdit (cust);
440 }
441 
442 void gncCustomerSetActive (GncCustomer *cust, gboolean active)
443 {
444  if (!cust) return;
445  if (active == cust->active) return;
446  gncCustomerBeginEdit (cust);
447  cust->active = active;
448  mark_customer (cust);
449  gncCustomerCommitEdit (cust);
450 }
451 
452 void gncCustomerSetDiscount (GncCustomer *cust, gnc_numeric discount)
453 {
454  if (!cust) return;
455  if (gnc_numeric_equal (discount, cust->discount)) return;
456  gncCustomerBeginEdit (cust);
457  cust->discount = discount;
458  mark_customer (cust);
459  gncCustomerCommitEdit (cust);
460 }
461 
462 void gncCustomerSetCredit (GncCustomer *cust, gnc_numeric credit)
463 {
464  if (!cust) return;
465  if (gnc_numeric_equal (credit, cust->credit)) return;
466  gncCustomerBeginEdit (cust);
467  cust->credit = credit;
468  mark_customer (cust);
469  gncCustomerCommitEdit (cust);
470 }
471 
472 void gncCustomerSetCurrency (GncCustomer *cust, gnc_commodity *currency)
473 {
474  if (!cust || !currency) return;
475  if (cust->currency && gnc_commodity_equal (cust->currency, currency)) return;
476  gncCustomerBeginEdit (cust);
477  cust->currency = currency;
478  mark_customer (cust);
479  gncCustomerCommitEdit (cust);
480 }
481 
482 void gncCustomerSetTaxTableOverride (GncCustomer *customer, gboolean override)
483 {
484  if (!customer) return;
485  if (customer->taxtable_override == override) return;
486  gncCustomerBeginEdit (customer);
487  customer->taxtable_override = override;
488  mark_customer (customer);
489  gncCustomerCommitEdit (customer);
490 }
491 
492 void gncCustomerSetTaxTable (GncCustomer *customer, GncTaxTable *table)
493 {
494  if (!customer) return;
495  if (customer->taxtable == table) return;
496 
497  gncCustomerBeginEdit (customer);
498  if (customer->taxtable)
499  gncTaxTableDecRef (customer->taxtable);
500  if (table)
501  gncTaxTableIncRef (table);
502  customer->taxtable = table;
503  mark_customer (customer);
504  gncCustomerCommitEdit (customer);
505 }
506 
507 /* Note that JobList changes do not affect the "dirtiness" of the customer */
508 void gncCustomerAddJob (GncCustomer *cust, GncJob *job)
509 {
510  if (!cust) return;
511  if (!job) return;
512 
513  if (g_list_index(cust->jobs, job) == -1)
514  cust->jobs = g_list_insert_sorted (cust->jobs, job,
515  (GCompareFunc)gncJobCompare);
516 
517  qof_event_gen (&cust->inst, QOF_EVENT_MODIFY, NULL);
518 }
519 
520 void gncCustomerRemoveJob (GncCustomer *cust, GncJob *job)
521 {
522  GList *node;
523 
524  if (!cust) return;
525  if (!job) return;
526 
527  node = g_list_find (cust->jobs, job);
528  if (!node)
529  {
530  /* PERR ("split not in account"); */
531  }
532  else
533  {
534  cust->jobs = g_list_remove_link (cust->jobs, node);
535  g_list_free_1 (node);
536  }
537  qof_event_gen (&cust->inst, QOF_EVENT_MODIFY, NULL);
538 }
539 
540 void gncCustomerBeginEdit (GncCustomer *cust)
541 {
542  qof_begin_edit (&cust->inst);
543 }
544 
545 static void gncCustomerOnError (QofInstance *inst, QofBackendError errcode)
546 {
547  PERR("Customer QofBackend Failure: %d", errcode);
548  gnc_engine_signal_commit_error( errcode );
549 }
550 
551 static void gncCustomerOnDone (QofInstance *inst)
552 {
553  GncCustomer *cust = (GncCustomer *) inst;
554  gncAddressClearDirty (cust->addr);
555  gncAddressClearDirty (cust->shipaddr);
556 }
557 
558 static void cust_free (QofInstance *inst)
559 {
560  GncCustomer *cust = (GncCustomer *) inst;
561  gncCustomerFree (cust);
562 }
563 
564 void gncCustomerCommitEdit (GncCustomer *cust)
565 {
566  if (!qof_commit_edit (QOF_INSTANCE(cust))) return;
567  qof_commit_edit_part2 (&cust->inst, gncCustomerOnError,
568  gncCustomerOnDone, cust_free);
569 }
570 
571 /* ============================================================== */
572 /* Get Functions */
573 
574 const char * gncCustomerGetID (const GncCustomer *cust)
575 {
576  if (!cust) return NULL;
577  return cust->id;
578 }
579 
580 const char * gncCustomerGetName (const GncCustomer *cust)
581 {
582  if (!cust) return NULL;
583  return cust->name;
584 }
585 
586 GncAddress * gncCustomerGetAddr (const GncCustomer *cust)
587 {
588  if (!cust) return NULL;
589  return cust->addr;
590 }
591 
592 static void
593 qofCustomerSetAddr (GncCustomer *cust, QofInstance *addr_ent)
594 {
595  GncAddress *addr;
596 
597  if (!cust || !addr_ent)
598  {
599  return;
600  }
601  addr = (GncAddress*)addr_ent;
602  if (addr == cust->addr)
603  {
604  return;
605  }
606  if (cust->addr != NULL)
607  {
608  gncAddressBeginEdit(cust->addr);
609  gncAddressDestroy(cust->addr);
610  }
611  gncCustomerBeginEdit(cust);
612  cust->addr = addr;
613  gncCustomerCommitEdit(cust);
614 }
615 
616 static void
617 qofCustomerSetShipAddr (GncCustomer *cust, QofInstance *ship_addr_ent)
618 {
619  GncAddress *ship_addr;
620 
621  if (!cust || !ship_addr_ent)
622  {
623  return;
624  }
625  ship_addr = (GncAddress*)ship_addr_ent;
626  if (ship_addr == cust->shipaddr)
627  {
628  return;
629  }
630  if (cust->shipaddr != NULL)
631  {
632  gncAddressBeginEdit(cust->shipaddr);
633  gncAddressDestroy(cust->shipaddr);
634  }
635  gncCustomerBeginEdit(cust);
636  cust->shipaddr = ship_addr;
637  gncCustomerCommitEdit(cust);
638 }
639 
640 GncAddress * gncCustomerGetShipAddr (const GncCustomer *cust)
641 {
642  if (!cust) return NULL;
643  return cust->shipaddr;
644 }
645 
646 const char * gncCustomerGetNotes (const GncCustomer *cust)
647 {
648  if (!cust) return NULL;
649  return cust->notes;
650 }
651 
652 GncBillTerm * gncCustomerGetTerms (const GncCustomer *cust)
653 {
654  if (!cust) return NULL;
655  return cust->terms;
656 }
657 
658 GncTaxIncluded gncCustomerGetTaxIncluded (const GncCustomer *cust)
659 {
660  if (!cust) return GNC_TAXINCLUDED_USEGLOBAL;
661  return cust->taxincluded;
662 }
663 
664 gnc_commodity * gncCustomerGetCurrency (const GncCustomer *cust)
665 {
666  if (!cust) return NULL;
667  return cust->currency;
668 }
669 
670 gboolean gncCustomerGetActive (const GncCustomer *cust)
671 {
672  if (!cust) return FALSE;
673  return cust->active;
674 }
675 
676 gnc_numeric gncCustomerGetDiscount (const GncCustomer *cust)
677 {
678  if (!cust) return gnc_numeric_zero();
679  return cust->discount;
680 }
681 
682 gnc_numeric gncCustomerGetCredit (const GncCustomer *cust)
683 {
684  if (!cust) return gnc_numeric_zero();
685  return cust->credit;
686 }
687 
688 gboolean gncCustomerGetTaxTableOverride (const GncCustomer *customer)
689 {
690  if (!customer) return FALSE;
691  return customer->taxtable_override;
692 }
693 
694 GncTaxTable* gncCustomerGetTaxTable (const GncCustomer *customer)
695 {
696  if (!customer) return NULL;
697  return customer->taxtable;
698 }
699 
700 GList * gncCustomerGetJoblist (const GncCustomer *cust, gboolean show_all)
701 {
702  if (!cust) return NULL;
703 
704  if (show_all)
705  {
706  return (g_list_copy (cust->jobs));
707  }
708  else
709  {
710  GList *list = NULL, *iterator;
711  for (iterator = cust->jobs; iterator; iterator = iterator->next)
712  {
713  GncJob *j = iterator->data;
714  if (gncJobGetActive (j))
715  list = g_list_append (list, j);
716  }
717  return list;
718  }
719 }
720 
721 gboolean gncCustomerIsDirty (GncCustomer *cust)
722 {
723  if (!cust) return FALSE;
724  return (qof_instance_is_dirty(&cust->inst) ||
725  gncAddressIsDirty (cust->addr) ||
726  gncAddressIsDirty (cust->shipaddr));
727 }
728 
729 /* Other functions */
730 
731 int gncCustomerCompare (const GncCustomer *a, const GncCustomer *b)
732 {
733  if (!a && !b) return 0;
734  if (!a && b) return 1;
735  if (a && !b) return -1;
736 
737  return(strcmp(a->name, b->name));
738 }
739 
740 gboolean
742 {
743  if (a == NULL && b == NULL) return TRUE;
744  if (a == NULL || b == NULL) return FALSE;
745 
746  g_return_val_if_fail(GNC_IS_CUSTOMER(a), FALSE);
747  g_return_val_if_fail(GNC_IS_CUSTOMER(b), FALSE);
748 
749  if (g_strcmp0(a->id, b->id) != 0)
750  {
751  PWARN("IDs differ: %s vs %s", a->id, b->id);
752  return FALSE;
753  }
754 
755  if (g_strcmp0(a->name, b->name) != 0)
756  {
757  PWARN("Names differ: %s vs %s", a->name, b->name);
758  return FALSE;
759  }
760 
761  if (g_strcmp0(a->notes, b->notes) != 0)
762  {
763  PWARN("Notes differ: %s vs %s", a->notes, b->notes);
764  return FALSE;
765  }
766 
767  if (!gncBillTermEqual(a->terms, b->terms))
768  {
769  PWARN("Bill terms differ");
770  return FALSE;
771  }
772 
773  if (!gnc_commodity_equal(a->currency, b->currency))
774  {
775  PWARN("currencies differ");
776  return FALSE;
777  }
778 
779  if (!gncTaxTableEqual(a->taxtable, b->taxtable))
780  {
781  PWARN("tax tables differ");
782  return FALSE;
783  }
784 
785  if (a->taxtable_override != b->taxtable_override)
786  {
787  PWARN("Tax table override flags differ");
788  return FALSE;
789  }
790 
791  if (a->taxincluded != b->taxincluded)
792  {
793  PWARN("Tax included flags differ");
794  return FALSE;
795  }
796 
797  if (a->active != b->active)
798  {
799  PWARN("Active flags differ");
800  return FALSE;
801  }
802 
803  if (!gncAddressEqual(a->addr, b->addr))
804  {
805  PWARN("addresses differ");
806  return FALSE;
807  }
808  if (!gncAddressEqual(a->shipaddr, b->shipaddr))
809  {
810  PWARN("addresses differ");
811  return FALSE;
812  }
813 
814  if (!gnc_numeric_equal(a->credit, b->credit))
815  {
816  PWARN("Credit amounts differ");
817  return FALSE;
818  }
819 
820  if (!gnc_numeric_equal(a->discount, b->discount))
821  {
822  PWARN("Discount amounts differ");
823  return FALSE;
824  }
825 
826  /* FIXME: Need to check jobs list
827  GList * jobs;
828  */
829 
830  return TRUE;
831 }
832 
842 static void
843 listen_for_address_events(QofInstance *entity, QofEventId event_type,
844  gpointer user_data, gpointer event_data)
845 {
846  GncCustomer* cust;
847 
848  if ((event_type & QOF_EVENT_MODIFY) == 0)
849  {
850  return;
851  }
852  if (!GNC_IS_ADDRESS(entity))
853  {
854  return;
855  }
856  if (!GNC_IS_CUSTOMER(event_data))
857  {
858  return;
859  }
860  cust = GNC_CUSTOMER(event_data);
861  gncCustomerBeginEdit(cust);
862  mark_customer(cust);
863  gncCustomerCommitEdit(cust);
864 }
865 /* ============================================================== */
866 /* Package-Private functions */
867 static const char * _gncCustomerPrintable (gpointer item)
868 {
869 // GncCustomer *c = item;
870  if (!item) return "failed";
871  return gncCustomerGetName((GncCustomer*)item);
872 }
873 
874 static void
875 destroy_customer_on_book_close(QofInstance *ent, gpointer data)
876 {
877  GncCustomer* c = GNC_CUSTOMER(ent);
878 
879  gncCustomerBeginEdit(c);
880  gncCustomerDestroy(c);
881 }
882 
887 static void
888 gnc_customer_book_end(QofBook* book)
889 {
890  QofCollection *col;
891 
892  col = qof_book_get_collection(book, GNC_ID_CUSTOMER);
893  qof_collection_foreach(col, destroy_customer_on_book_close, NULL);
894 }
895 
896 static QofObject gncCustomerDesc =
897 {
898  DI(.interface_version = ) QOF_OBJECT_VERSION,
899  DI(.e_type = ) _GNC_MOD_NAME,
900  DI(.type_label = ) "Customer",
901  DI(.create = ) (gpointer)gncCustomerCreate,
902  DI(.book_begin = ) NULL,
903  DI(.book_end = ) gnc_customer_book_end,
904  DI(.is_dirty = ) qof_collection_is_dirty,
905  DI(.mark_clean = ) qof_collection_mark_clean,
906  DI(.foreach = ) qof_collection_foreach,
907  DI(.printable = ) (const char * (*)(gpointer))gncCustomerGetName,
908  DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
909 };
910 
911 gboolean gncCustomerRegister (void)
912 {
913  static QofParam params[] =
914  {
915  { CUSTOMER_ID, QOF_TYPE_STRING, (QofAccessFunc)gncCustomerGetID, (QofSetterFunc)gncCustomerSetID },
916  { CUSTOMER_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncCustomerGetName, (QofSetterFunc)gncCustomerSetName },
917  { CUSTOMER_NOTES, QOF_TYPE_STRING, (QofAccessFunc)gncCustomerGetNotes, (QofSetterFunc)gncCustomerSetNotes },
918  {
919  CUSTOMER_DISCOUNT, QOF_TYPE_NUMERIC, (QofAccessFunc)gncCustomerGetDiscount,
920  (QofSetterFunc)gncCustomerSetDiscount
921  },
922  {
923  CUSTOMER_CREDIT, QOF_TYPE_NUMERIC, (QofAccessFunc)gncCustomerGetCredit,
924  (QofSetterFunc)gncCustomerSetCredit
925  },
926  { CUSTOMER_ADDR, GNC_ID_ADDRESS, (QofAccessFunc)gncCustomerGetAddr, (QofSetterFunc)qofCustomerSetAddr },
927  { CUSTOMER_SHIPADDR, GNC_ID_ADDRESS, (QofAccessFunc)gncCustomerGetShipAddr, (QofSetterFunc)qofCustomerSetShipAddr },
928  {
929  CUSTOMER_TT_OVER, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncCustomerGetTaxTableOverride,
930  (QofSetterFunc)gncCustomerSetTaxTableOverride
931  },
932  { CUSTOMER_TERMS, GNC_ID_BILLTERM, (QofAccessFunc)gncCustomerGetTerms, (QofSetterFunc)gncCustomerSetTerms },
933  { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncCustomerGetActive, (QofSetterFunc)gncCustomerSetActive },
934  { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
935  { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
936  { NULL },
937  };
938 
939  if (!qof_choice_add_class(GNC_ID_INVOICE, GNC_ID_CUSTOMER, INVOICE_OWNER))
940  {
941  return FALSE;
942  }
943  if (!qof_choice_add_class(GNC_ID_JOB, GNC_ID_CUSTOMER, JOB_OWNER))
944  {
945  return FALSE;
946  }
947  qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncCustomerCompare, params);
948  if (!qof_choice_create(GNC_ID_CUSTOMER))
949  {
950  return FALSE;
951  }
952  /* temp */
953  _gncCustomerPrintable(NULL);
954  return qof_object_register (&gncCustomerDesc);
955 }
956 
957 gchar *gncCustomerNextID (QofBook *book)
958 {
959  return qof_book_increment_and_format_counter (book, _GNC_MOD_NAME);
960 }
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
Core Customer Interface.
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
const GncGUID * qof_instance_get_guid(gconstpointer)
#define qof_instance_is_dirty
Definition: qofinstance.h:165
QofBook * qof_instance_get_book(gconstpointer)
gboolean qof_collection_is_dirty(const QofCollection *col)
GncTaxIncluded
Definition: gncTaxTable.h:100
QofBackendError
The errors that can be reported to the GUI & other front-end users.
Definition: qofbackend.h:59
gchar * qof_book_increment_and_format_counter(QofBook *book, const char *counter_name)
GList * qof_instance_get_referring_object_list_from_collection(const QofCollection *coll, const QofInstance *ref)
void qof_class_register(QofIdTypeConst obj_name, QofSortFunc default_sort_fcn, const QofParam *params)
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
QofCollection * qof_instance_get_collection(gconstpointer inst)
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 QOF_PARAM_BOOK
Definition: qofquery.h:109
void qof_collection_foreach(const QofCollection *, QofInstanceForeachCB, gpointer user_data)
gboolean gncBillTermEqual(const GncBillTerm *a, const GncBillTerm *b)
Definition: gncBillTerm.c:647
gint qof_event_register_handler(QofEventHandler handler, gpointer handler_data)
Register a handler for events.
#define PWARN(format, args...)
Definition: qoflog.h:243
void qof_instance_init_data(QofInstance *, QofIdType, QofBook *)
gboolean qof_begin_edit(QofInstance *inst)
gint QofEventId
Definition: qofevent.h:45
Definition: gncJob.c:41
gboolean qof_choice_create(char *type)
Set an object as using QOF_TYPE_CHOICE.
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 *)
gboolean gncAddressEqual(const GncAddress *a, const GncAddress *b)
Deeply compare two addresses.
Definition: gncAddress.c:579
Business Invoice Interface.
gboolean gncCustomerEqual(const GncCustomer *a, const GncCustomer *b)
Definition: gncCustomer.c:741
gboolean qof_choice_add_class(const char *choice, char *add, char *param_name)
Add the choices for this parameter to the object.
void(* QofSetterFunc)(gpointer, gpointer)
Definition: qofclass.h:184
QofCollection * qof_book_get_collection(const QofBook *, QofIdType)
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