33 #include <qofinstance-p.h> 37 #include "gncAddressP.h" 38 #include "gncBillTermP.h" 43 #include "gncCustomerP.h" 45 #include "gncTaxTableP.h" 47 static gint cust_qof_event_handler_id = 0;
49 gpointer user_data, gpointer event_data);
61 gnc_commodity * currency;
63 gboolean taxtable_override;
67 gnc_numeric * balance;
77 QofInstanceClass parent_class;
80 static QofLogModule log_module = GNC_MOD_BUSINESS;
82 #define _GNC_MOD_NAME GNC_ID_CUSTOMER 87 static inline void mark_customer (
GncCustomer *customer);
90 qof_instance_set_dirty(&customer->inst);
102 PROP_PAYMENT_LAST_ACCT,
106 G_DEFINE_TYPE(
GncCustomer, gnc_customer, QOF_TYPE_INSTANCE)
114 gnc_customer_dispose(GObject *custp)
116 G_OBJECT_CLASS(gnc_customer_parent_class)->dispose(custp);
120 gnc_customer_finalize(GObject* custp)
122 G_OBJECT_CLASS(gnc_customer_parent_class)->finalize(custp);
126 gnc_customer_get_property (GObject *
object,
132 g_return_if_fail(GNC_IS_CUSTOMER(
object));
134 cust = GNC_CUSTOMER(
object);
138 g_value_set_string(value, cust->name);
140 case PROP_PDF_DIRNAME:
143 case PROP_LAST_POSTED:
146 case PROP_PAYMENT_LAST_ACCT:
150 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, prop_id, pspec);
156 gnc_customer_set_property (GObject *
object,
163 g_return_if_fail(GNC_IS_CUSTOMER(
object));
165 cust = GNC_CUSTOMER(
object);
166 g_assert (qof_instance_get_editlevel(cust));
171 gncCustomerSetName(cust, g_value_get_string(value));
173 case PROP_PDF_DIRNAME:
176 case PROP_LAST_POSTED:
179 case PROP_PAYMENT_LAST_ACCT:
183 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, prop_id, pspec);
194 g_return_val_if_fail(inst != NULL, FALSE);
195 g_return_val_if_fail(GNC_IS_CUSTOMER(inst), FALSE);
197 cust = GNC_CUSTOMER(inst);
199 return g_strdup_printf(
"Customer %s", cust->name);
208 g_return_val_if_fail(inst != NULL, FALSE);
209 g_return_val_if_fail(GNC_IS_CUSTOMER(inst), FALSE);
211 cust = GNC_CUSTOMER(inst);
213 if (GNC_IS_BILLTERM(ref))
215 return (cust->terms == GNC_BILLTERM(ref));
217 else if (GNC_IS_TAXTABLE(ref))
219 return (cust->taxtable == GNC_TAXTABLE(ref));
234 if (!GNC_IS_BILLTERM(ref) && !GNC_IS_TAXTABLE(ref))
243 gnc_customer_class_init (GncCustomerClass *klass)
245 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
246 QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
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;
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;
257 g_object_class_install_property
260 g_param_spec_string (
"name",
262 "The customer is an arbitrary string " 263 "assigned by the user which provides the " 268 g_object_class_install_property
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 " 281 g_object_class_install_property(
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.",
291 g_object_class_install_property(
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.",
307 if (!book)
return NULL;
309 cust = g_object_new (GNC_TYPE_CUSTOMER, NULL);
312 cust->id = CACHE_INSERT (
"");
313 cust->name = CACHE_INSERT (
"");
314 cust->notes = CACHE_INSERT (
"");
315 cust->addr = gncAddressCreate (book, &cust->inst);
319 cust->balance = NULL;
321 cust->discount = gnc_numeric_zero();
322 cust->credit = gnc_numeric_zero();
323 cust->shipaddr = gncAddressCreate (book, &cust->inst);
325 if (cust_qof_event_handler_id == 0)
336 qof_instance_set_destroying(cust, TRUE);
337 qof_instance_set_dirty (&cust->inst);
338 gncCustomerCommitEdit (cust);
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);
355 gncJobFreeList (cust->jobs);
356 g_list_free (cust->jobs);
357 g_free (cust->balance);
362 gncBillTermDecRef (cust->terms);
364 gncTaxTableDecRef (cust->taxtable);
368 g_object_unref (cust);
374 #define SET_STR(obj, member, str) { \ 375 if (!g_strcmp0 (member, str)) return; \ 376 gncCustomerBeginEdit (obj); \ 377 CACHE_REPLACE(member, str); \ 380 void gncCustomerSetID (
GncCustomer *cust,
const char *
id)
384 SET_STR(cust, cust->id,
id);
385 mark_customer (cust);
386 gncCustomerCommitEdit (cust);
389 void gncCustomerSetName (
GncCustomer *cust,
const char *name)
393 SET_STR(cust, cust->name, name);
394 mark_customer (cust);
395 gncCustomerCommitEdit (cust);
398 void gncCustomerSetNotes (
GncCustomer *cust,
const char *notes)
402 SET_STR(cust, cust->notes, notes);
403 mark_customer (cust);
404 gncCustomerCommitEdit (cust);
407 void gncCustomerSetTerms (
GncCustomer *cust, GncBillTerm *terms)
410 if (cust->terms == terms)
return;
412 gncCustomerBeginEdit (cust);
414 gncBillTermDecRef (cust->terms);
417 gncBillTermIncRef (cust->terms);
418 mark_customer (cust);
419 gncCustomerCommitEdit (cust);
425 if (taxincl == cust->taxincluded)
return;
426 gncCustomerBeginEdit (cust);
427 cust->taxincluded = taxincl;
428 mark_customer (cust);
429 gncCustomerCommitEdit (cust);
432 void gncCustomerSetActive (
GncCustomer *cust, gboolean active)
435 if (active == cust->active)
return;
436 gncCustomerBeginEdit (cust);
437 cust->active = active;
438 mark_customer (cust);
439 gncCustomerCommitEdit (cust);
442 void gncCustomerSetDiscount (
GncCustomer *cust, gnc_numeric discount)
446 gncCustomerBeginEdit (cust);
447 cust->discount = discount;
448 mark_customer (cust);
449 gncCustomerCommitEdit (cust);
452 void gncCustomerSetCredit (
GncCustomer *cust, gnc_numeric credit)
456 gncCustomerBeginEdit (cust);
457 cust->credit = credit;
458 mark_customer (cust);
459 gncCustomerCommitEdit (cust);
462 void gncCustomerSetCurrency (
GncCustomer *cust, gnc_commodity *currency)
464 if (!cust || !currency)
return;
466 gncCustomerBeginEdit (cust);
467 cust->currency = currency;
468 mark_customer (cust);
469 gncCustomerCommitEdit (cust);
472 void gncCustomerSetTaxTableOverride (
GncCustomer *customer, gboolean
override)
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);
484 if (!customer)
return;
485 if (customer->taxtable ==
table)
return;
487 gncCustomerBeginEdit (customer);
488 if (customer->taxtable)
489 gncTaxTableDecRef (customer->taxtable);
491 gncTaxTableIncRef (
table);
492 customer->taxtable =
table;
493 mark_customer (customer);
494 gncCustomerCommitEdit (customer);
498 void gncCustomerAddJob (
GncCustomer *cust, GncJob *job)
503 if (g_list_index(cust->jobs, job) == -1)
504 cust->jobs = g_list_insert_sorted (cust->jobs, job,
505 (GCompareFunc)gncJobCompare);
510 void gncCustomerRemoveJob (
GncCustomer *cust, GncJob *job)
517 node = g_list_find (cust->jobs, job);
524 cust->jobs = g_list_remove_link (cust->jobs, node);
525 g_list_free_1 (node);
537 PERR(
"Customer QofBackend Failure: %d", errcode);
538 gnc_engine_signal_commit_error( errcode );
544 gncAddressClearDirty (cust->addr);
545 gncAddressClearDirty (cust->shipaddr);
551 gncCustomerFree (cust);
558 gncCustomerOnDone, cust_free);
564 const char * gncCustomerGetID (
const GncCustomer *cust)
566 if (!cust)
return NULL;
570 const char * gncCustomerGetName (
const GncCustomer *cust)
572 if (!cust)
return NULL;
578 if (!cust)
return NULL;
587 if (!cust || !addr_ent)
592 if (addr == cust->addr)
596 if (cust->addr != NULL)
598 gncAddressBeginEdit(cust->addr);
599 gncAddressDestroy(cust->addr);
601 gncCustomerBeginEdit(cust);
603 gncCustomerCommitEdit(cust);
611 if (!cust || !ship_addr_ent)
616 if (ship_addr == cust->shipaddr)
620 if (cust->shipaddr != NULL)
622 gncAddressBeginEdit(cust->shipaddr);
623 gncAddressDestroy(cust->shipaddr);
625 gncCustomerBeginEdit(cust);
626 cust->shipaddr = ship_addr;
627 gncCustomerCommitEdit(cust);
632 if (!cust)
return NULL;
633 return cust->shipaddr;
636 const char * gncCustomerGetNotes (
const GncCustomer *cust)
638 if (!cust)
return NULL;
642 GncBillTerm * gncCustomerGetTerms (
const GncCustomer *cust)
644 if (!cust)
return NULL;
651 return cust->taxincluded;
654 gnc_commodity * gncCustomerGetCurrency (
const GncCustomer *cust)
656 if (!cust)
return NULL;
657 return cust->currency;
660 gboolean gncCustomerGetActive (
const GncCustomer *cust)
662 if (!cust)
return FALSE;
666 gnc_numeric gncCustomerGetDiscount (
const GncCustomer *cust)
668 if (!cust)
return gnc_numeric_zero();
669 return cust->discount;
672 gnc_numeric gncCustomerGetCredit (
const GncCustomer *cust)
674 if (!cust)
return gnc_numeric_zero();
678 gboolean gncCustomerGetTaxTableOverride (
const GncCustomer *customer)
680 if (!customer)
return FALSE;
681 return customer->taxtable_override;
686 if (!customer)
return NULL;
687 return customer->taxtable;
690 GList * gncCustomerGetJoblist (
const GncCustomer *cust, gboolean show_all)
692 if (!cust)
return NULL;
696 return (g_list_copy (cust->jobs));
700 GList *list = NULL, *iterator;
701 for (iterator = cust->jobs; iterator; iterator = iterator->next)
703 GncJob *j = iterator->data;
704 if (gncJobGetActive (j))
705 list = g_list_prepend (list, j);
707 return g_list_reverse (list);
713 if (!cust)
return FALSE;
715 gncAddressIsDirty (cust->addr) ||
716 gncAddressIsDirty (cust->shipaddr));
723 if (!a && !b)
return 0;
724 if (!a && b)
return 1;
725 if (a && !b)
return -1;
727 return(strcmp(a->name, b->name));
733 if (a == NULL && b == NULL)
return TRUE;
734 if (a == NULL || b == NULL)
return FALSE;
736 g_return_val_if_fail(GNC_IS_CUSTOMER(a), FALSE);
737 g_return_val_if_fail(GNC_IS_CUSTOMER(b), FALSE);
739 if (g_strcmp0(a->id, b->id) != 0)
741 PWARN(
"IDs differ: %s vs %s", a->id, b->id);
745 if (g_strcmp0(a->name, b->name) != 0)
747 PWARN(
"Names differ: %s vs %s", a->name, b->name);
751 if (g_strcmp0(a->notes, b->notes) != 0)
753 PWARN(
"Notes differ: %s vs %s", a->notes, b->notes);
759 PWARN(
"Bill terms differ");
765 PWARN(
"currencies differ");
769 if (!gncTaxTableEqual(a->taxtable, b->taxtable))
771 PWARN(
"tax tables differ");
775 if (a->taxtable_override != b->taxtable_override)
777 PWARN(
"Tax table override flags differ");
781 if (a->taxincluded != b->taxincluded)
783 PWARN(
"Tax included flags differ");
787 if (a->active != b->active)
789 PWARN(
"Active flags differ");
795 PWARN(
"addresses differ");
800 PWARN(
"addresses differ");
806 PWARN(
"Credit amounts differ");
812 PWARN(
"Discount amounts differ");
837 gpointer user_data, gpointer event_data)
840 if ((GNC_IS_ADDRESS (entity) &&
841 (event_type & QOF_EVENT_MODIFY) != 0))
843 if (GNC_IS_CUSTOMER (event_data))
846 gncCustomerBeginEdit (cust);
847 mark_customer (cust);
848 gncCustomerCommitEdit (cust);
854 if (GNC_IS_LOT (entity))
856 GNCLot *lot = GNC_LOT (entity);
873 g_free (cust->balance);
874 cust->balance = NULL;
882 static const char * _gncCustomerPrintable (gpointer item)
885 if (!item)
return "failed";
890 destroy_customer_on_book_close(
QofInstance *ent, gpointer data)
894 gncCustomerBeginEdit(c);
895 gncCustomerDestroy(c);
903 gnc_customer_book_end(QofBook* book)
908 qof_collection_foreach(col, destroy_customer_on_book_close, NULL);
911 static QofObject gncCustomerDesc =
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,
921 DI(.foreach = ) qof_collection_foreach,
922 DI(.printable = ) (const
char * (*)(gpointer))gncCustomerGetName,
926 gboolean gncCustomerRegister (
void)
928 static QofParam params[] =
934 CUSTOMER_DISCOUNT, QOF_TYPE_NUMERIC, (
QofAccessFunc)gncCustomerGetDiscount,
938 CUSTOMER_CREDIT, QOF_TYPE_NUMERIC, (
QofAccessFunc)gncCustomerGetCredit,
944 CUSTOMER_TT_OVER, QOF_TYPE_BOOLEAN, (
QofAccessFunc)gncCustomerGetTaxTableOverride,
956 _gncCustomerPrintable(NULL);
960 gchar *gncCustomerNextID (QofBook *book)
968 return cust->balance;
971 void gncCustomerSetCachedBalance (
GncCustomer *cust,
const gnc_numeric *new_bal)
977 g_free (cust->balance);
978 cust->balance = NULL;
984 cust->balance = g_new0 (gnc_numeric, 1);
986 *cust->balance = *new_bal;
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
Compare two instances, based on their last update times.
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b represent the same number.
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.
#define qof_instance_is_dirty
Return value of is_dirty flag.
QofBook * qof_instance_get_book(gconstpointer inst)
Return the book pointer.
gboolean qof_collection_is_dirty(const QofCollection *col)
Return value of 'dirty' flag on collection.
GncTaxIncluded
How to interpret the TaxIncluded.
QofBackendError
The errors that can be reported to the GUI & other front-end users.
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.
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.
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equal.
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.
#define QOF_OBJECT_VERSION
Defines the version of the core object object registration interface.
gboolean qof_commit_edit(QofInstance *inst)
commit_edit helpers
#define PERR(format, args...)
Log a serious error.
#define QOF_PARAM_BOOK
"Known" Object Parameters – all objects must support these
void(* QofSetterFunc)(gpointer, gpointer)
The QofSetterFunc defines an function pointer for parameter setters.
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.
gint qof_event_register_handler(QofEventHandler handler, gpointer user_data)
Register a handler for events.
#define PWARN(format, args...)
Log a warning.
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.
– Business Helper Functions
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.
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
The QofAccessFunc defines an arbitrary function pointer for access functions.
void qof_collection_mark_clean(QofCollection *)
reset value of dirty flag
gboolean gncAddressEqual(const GncAddress *a, const GncAddress *b)
Deeply compare two addresses.
credit, discount and shipaddr are unique to GncCustomer id, name, notes, terms, addr, currency, taxtable, taxtable_override taxincluded, active and jobs are identical to ::GncVendor.
GncOwnerType gncOwnerGetType(const GncOwner *owner)
Returns the GncOwnerType of this owner.
const GncOwner * gncOwnerGetEndOwner(const GncOwner *owner)
Get the "parent" Owner or GncGUID thereof.
GncInvoice * gncInvoiceGetInvoiceFromLot(GNCLot *lot)
Given a LOT, find and return the Invoice attached to the lot.
Business Invoice Interface.
gboolean gncCustomerEqual(const GncCustomer *a, const GncCustomer *b)
Test support function, used in gets-dbi-business-stuff.c.
GncCustomer * gncOwnerGetCustomer(const GncOwner *owner)
If the given owner is of type GNC_OWNER_CUSTOMER, returns the pointer to the customer object...
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
gboolean qof_object_register(const QofObject *object)
Register new types of object objects.
gboolean qof_book_shutting_down(const QofBook *book)
Is the book shutting down?
void qof_event_gen(QofInstance *entity, QofEventId event_id, gpointer event_data)
Invoke all registered event handlers using the given arguments.
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