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