Line data Source code
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 :
69 : struct _gncVendorClass
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 79 : void mark_vendor (GncVendor *vendor)
83 : {
84 79 : qof_instance_set_dirty(&vendor->inst);
85 79 : qof_event_gen (&vendor->inst, QOF_EVENT_MODIFY, NULL);
86 79 : }
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 160 : G_DEFINE_TYPE(GncVendor, gnc_vendor, QOF_TYPE_INSTANCE)
111 :
112 : static void
113 26 : gnc_vendor_init(GncVendor* vendor)
114 : {
115 26 : }
116 :
117 : static void
118 14 : gnc_vendor_dispose(GObject *vendorp)
119 : {
120 14 : G_OBJECT_CLASS(gnc_vendor_parent_class)->dispose(vendorp);
121 14 : }
122 :
123 : static void
124 14 : gnc_vendor_finalize(GObject* vendorp)
125 : {
126 14 : G_OBJECT_CLASS(gnc_vendor_parent_class)->finalize(vendorp);
127 14 : }
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 13 : gnc_vendor_get_property (GObject *object,
137 : guint prop_id,
138 : GValue *value,
139 : GParamSpec *pspec)
140 : {
141 : GncVendor *vendor;
142 :
143 13 : g_return_if_fail(GNC_IS_VENDOR(object));
144 :
145 13 : vendor = GNC_VENDOR(object);
146 13 : switch (prop_id)
147 : {
148 1 : case PROP_NAME:
149 1 : g_value_set_string(value, vendor->name);
150 1 : break;
151 1 : case PROP_ID:
152 1 : g_value_set_string(value, vendor->id);
153 1 : break;
154 1 : case PROP_NOTES:
155 1 : g_value_set_string(value, vendor->notes);
156 1 : break;
157 1 : case PROP_CURRENCY:
158 1 : g_value_take_object(value, vendor->currency);
159 1 : break;
160 1 : case PROP_ACTIVE:
161 1 : g_value_set_boolean(value, vendor->active);
162 1 : break;
163 1 : case PROP_TAXTABLE_OVERRIDE:
164 1 : g_value_set_boolean(value, vendor->taxtable_override);
165 1 : break;
166 1 : case PROP_BILLTERMS:
167 1 : g_value_take_object(value, vendor->terms);
168 1 : break;
169 1 : case PROP_TAXTABLE:
170 1 : g_value_take_object(value, vendor->taxtable);
171 1 : break;
172 1 : case PROP_ADDRESS:
173 1 : g_value_take_object(value, vendor->addr);
174 1 : break;
175 0 : case PROP_TAX_INCLUDED:
176 0 : g_value_set_int(value, vendor->taxincluded);
177 0 : break;
178 1 : case PROP_TAX_INCLUDED_STR:
179 1 : g_value_set_string(value, qofVendorGetTaxIncluded(vendor));
180 1 : break;
181 1 : case PROP_PDF_DIRNAME:
182 1 : qof_instance_get_kvp (QOF_INSTANCE (vendor), value, 1, OWNER_EXPORT_PDF_DIRNAME);
183 1 : break;
184 1 : case PROP_LAST_POSTED:
185 1 : qof_instance_get_kvp (QOF_INSTANCE (vendor), value, 1, LAST_POSTED_TO_ACCT);
186 1 : break;
187 1 : case PROP_PAYMENT_LAST_ACCT:
188 1 : qof_instance_get_kvp (QOF_INSTANCE (vendor), value, 2, GNC_PAYMENT, GNC_LAST_ACCOUNT);
189 1 : break;
190 0 : default:
191 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
192 0 : break;
193 : }
194 : }
195 :
196 : static void
197 11 : gnc_vendor_set_property (GObject *object,
198 : guint prop_id,
199 : const GValue *value,
200 : GParamSpec *pspec)
201 : {
202 : GncVendor *vendor;
203 :
204 11 : g_return_if_fail(GNC_IS_VENDOR(object));
205 :
206 11 : vendor = GNC_VENDOR(object);
207 11 : g_assert (qof_instance_get_editlevel(vendor));
208 :
209 11 : switch (prop_id)
210 : {
211 1 : case PROP_NAME:
212 1 : gncVendorSetName(vendor, g_value_get_string(value));
213 1 : break;
214 1 : case PROP_ID:
215 1 : gncVendorSetID(vendor, g_value_get_string(value));
216 1 : break;
217 1 : case PROP_NOTES:
218 1 : gncVendorSetNotes(vendor, g_value_get_string(value));
219 1 : break;
220 1 : case PROP_CURRENCY:
221 1 : gncVendorSetCurrency(vendor, g_value_get_object(value));
222 1 : break;
223 1 : case PROP_ACTIVE:
224 1 : gncVendorSetActive(vendor, g_value_get_boolean(value));
225 1 : break;
226 1 : case PROP_TAXTABLE_OVERRIDE:
227 1 : gncVendorSetTaxTableOverride(vendor, g_value_get_boolean(value));
228 1 : break;
229 0 : case PROP_BILLTERMS:
230 0 : gncVendorSetTerms(vendor, g_value_get_object(value));
231 0 : break;
232 0 : case PROP_TAXTABLE:
233 0 : gncVendorSetTaxTable(vendor, g_value_get_object(value));
234 0 : break;
235 1 : case PROP_ADDRESS:
236 1 : qofVendorSetAddr(vendor, g_value_get_object(value));
237 1 : break;
238 0 : case PROP_TAX_INCLUDED:
239 0 : gncVendorSetTaxIncluded(vendor, (GncTaxIncluded)g_value_get_int(value));
240 0 : break;
241 1 : case PROP_TAX_INCLUDED_STR:
242 1 : qofVendorSetTaxIncluded(vendor, g_value_get_string(value));
243 1 : break;
244 1 : case PROP_PDF_DIRNAME:
245 1 : qof_instance_set_kvp (QOF_INSTANCE (vendor), value, 1, OWNER_EXPORT_PDF_DIRNAME);
246 1 : break;
247 1 : case PROP_LAST_POSTED:
248 1 : qof_instance_set_kvp (QOF_INSTANCE (vendor), value, 1, LAST_POSTED_TO_ACCT);
249 1 : break;
250 1 : case PROP_PAYMENT_LAST_ACCT:
251 1 : qof_instance_set_kvp (QOF_INSTANCE (vendor), value, 2, GNC_PAYMENT, GNC_LAST_ACCOUNT);
252 1 : break;
253 0 : default:
254 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
255 0 : break;
256 : }
257 : }
258 :
259 : /** Does this object refer to a specific object */
260 : static gboolean
261 0 : impl_refers_to_object(const QofInstance* inst, const QofInstance* ref)
262 : {
263 : GncVendor* v;
264 :
265 0 : g_return_val_if_fail(inst != NULL, FALSE);
266 0 : g_return_val_if_fail(GNC_IS_VENDOR(inst), FALSE);
267 :
268 0 : v = GNC_VENDOR(inst);
269 :
270 0 : if (GNC_IS_BILLTERM(ref))
271 : {
272 0 : return (v->terms == GNC_BILLTERM(ref));
273 : }
274 0 : else if (GNC_IS_TAXTABLE(ref))
275 : {
276 0 : return (v->taxtable == GNC_TAXTABLE(ref));
277 : }
278 :
279 0 : return FALSE;
280 : }
281 :
282 : /** Returns a list of my type of object which refers to an object. For example, when called as
283 : qof_instance_get_typed_referring_object_list(taxtable, account);
284 : it will return the list of taxtables which refer to a specific account. The result should be the
285 : same regardless of which taxtable object is used. The list must be freed by the caller but the
286 : objects on the list must not.
287 : */
288 : static GList*
289 0 : impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
290 : {
291 0 : if (!GNC_IS_BILLTERM(ref) && !GNC_IS_TAXTABLE(ref))
292 : {
293 0 : return NULL;
294 : }
295 :
296 0 : return qof_instance_get_referring_object_list_from_collection(qof_instance_get_collection(inst), ref);
297 : }
298 :
299 : static void
300 8 : gnc_vendor_class_init (GncVendorClass *klass)
301 : {
302 8 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
303 8 : QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
304 :
305 8 : gobject_class->dispose = gnc_vendor_dispose;
306 8 : gobject_class->finalize = gnc_vendor_finalize;
307 8 : gobject_class->set_property = gnc_vendor_set_property;
308 8 : gobject_class->get_property = gnc_vendor_get_property;
309 :
310 8 : qof_class->get_display_name = NULL;
311 8 : qof_class->refers_to_object = impl_refers_to_object;
312 8 : qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
313 :
314 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : }
451 :
452 : /* Create/Destroy Functions */
453 27 : GncVendor *gncVendorCreate (QofBook *book)
454 : {
455 : GncVendor *vendor;
456 :
457 27 : if (!book) return NULL;
458 :
459 26 : vendor = g_object_new (GNC_TYPE_VENDOR, NULL);
460 26 : qof_instance_init_data (&vendor->inst, _GNC_MOD_NAME, book);
461 :
462 26 : vendor->id = CACHE_INSERT ("");
463 26 : vendor->name = CACHE_INSERT ("");
464 26 : vendor->notes = CACHE_INSERT ("");
465 26 : vendor->addr = gncAddressCreate (book, &vendor->inst);
466 26 : vendor->taxincluded = GNC_TAXINCLUDED_USEGLOBAL;
467 26 : vendor->active = TRUE;
468 26 : vendor->jobs = NULL;
469 26 : vendor->balance = NULL;
470 :
471 26 : if (vend_qof_event_handler_id == 0)
472 8 : vend_qof_event_handler_id = qof_event_register_handler (vend_handle_qof_events, NULL);
473 :
474 26 : qof_event_gen (&vendor->inst, QOF_EVENT_CREATE, NULL);
475 :
476 26 : return vendor;
477 : }
478 :
479 13 : void gncVendorDestroy (GncVendor *vendor)
480 : {
481 13 : if (!vendor) return;
482 13 : qof_instance_set_destroying(vendor, TRUE);
483 13 : gncVendorCommitEdit (vendor);
484 : }
485 :
486 13 : static void gncVendorFree (GncVendor *vendor)
487 : {
488 13 : if (!vendor) return;
489 :
490 13 : qof_event_gen (&vendor->inst, QOF_EVENT_DESTROY, NULL);
491 :
492 13 : CACHE_REMOVE (vendor->id);
493 13 : CACHE_REMOVE (vendor->name);
494 13 : CACHE_REMOVE (vendor->notes);
495 13 : gncAddressBeginEdit (vendor->addr);
496 13 : gncAddressDestroy (vendor->addr);
497 :
498 13 : gncJobFreeList (vendor->jobs);
499 13 : g_list_free (vendor->jobs);
500 13 : g_free (vendor->balance);
501 :
502 13 : if (!qof_book_shutting_down (qof_instance_get_book (QOF_INSTANCE(vendor))))
503 : {
504 4 : if (vendor->terms)
505 0 : gncBillTermDecRef (vendor->terms);
506 4 : if (vendor->taxtable)
507 0 : gncTaxTableDecRef (vendor->taxtable);
508 : }
509 :
510 : /* qof_instance_release (&vendor->inst); */
511 13 : 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 17 : void gncVendorSetID (GncVendor *vendor, const char *id)
524 : {
525 17 : if (!vendor) return;
526 17 : if (!id) return;
527 17 : SET_STR(vendor, vendor->id, id);
528 17 : mark_vendor (vendor);
529 17 : gncVendorCommitEdit (vendor);
530 : }
531 :
532 11 : void gncVendorSetName (GncVendor *vendor, const char *name)
533 : {
534 11 : if (!vendor) return;
535 11 : if (!name) return;
536 11 : SET_STR(vendor, vendor->name, name);
537 11 : mark_vendor (vendor);
538 11 : gncVendorCommitEdit (vendor);
539 : }
540 :
541 7 : void gncVendorSetNotes (GncVendor *vendor, const char *notes)
542 : {
543 7 : if (!vendor) return;
544 7 : if (!notes) return;
545 7 : SET_STR(vendor, vendor->notes, notes);
546 6 : mark_vendor (vendor);
547 6 : gncVendorCommitEdit (vendor);
548 : }
549 :
550 0 : void gncVendorSetTerms (GncVendor *vendor, GncBillTerm *terms)
551 : {
552 0 : if (!vendor) return;
553 0 : if (vendor->terms == terms) return;
554 :
555 0 : gncVendorBeginEdit (vendor);
556 0 : if (vendor->terms)
557 0 : gncBillTermDecRef (vendor->terms);
558 0 : vendor->terms = terms;
559 0 : if (vendor->terms)
560 0 : gncBillTermIncRef (vendor->terms);
561 0 : mark_vendor (vendor);
562 0 : gncVendorCommitEdit (vendor);
563 : }
564 :
565 8 : void gncVendorSetTaxIncluded (GncVendor *vendor, GncTaxIncluded taxincl)
566 : {
567 8 : if (!vendor) return;
568 8 : if (taxincl == vendor->taxincluded) return;
569 5 : gncVendorBeginEdit (vendor);
570 5 : vendor->taxincluded = taxincl;
571 5 : mark_vendor (vendor);
572 5 : gncVendorCommitEdit (vendor);
573 : }
574 :
575 16 : void gncVendorSetCurrency (GncVendor *vendor, gnc_commodity *currency)
576 : {
577 16 : if (!vendor || !currency) return;
578 16 : if (vendor->currency &&
579 0 : gnc_commodity_equal (vendor->currency, currency))
580 0 : return;
581 16 : gncVendorBeginEdit (vendor);
582 16 : vendor->currency = currency;
583 16 : mark_vendor (vendor);
584 16 : gncVendorCommitEdit (vendor);
585 : }
586 :
587 11 : void gncVendorSetActive (GncVendor *vendor, gboolean active)
588 : {
589 11 : if (!vendor) return;
590 11 : if (active == vendor->active) return;
591 6 : gncVendorBeginEdit (vendor);
592 6 : vendor->active = active;
593 6 : mark_vendor (vendor);
594 6 : gncVendorCommitEdit (vendor);
595 : }
596 :
597 4 : void gncVendorSetTaxTableOverride (GncVendor *vendor, gboolean override)
598 : {
599 4 : if (!vendor) return;
600 4 : if (vendor->taxtable_override == override) return;
601 0 : gncVendorBeginEdit (vendor);
602 0 : vendor->taxtable_override = override;
603 0 : mark_vendor (vendor);
604 0 : gncVendorCommitEdit (vendor);
605 : }
606 :
607 0 : void gncVendorSetTaxTable (GncVendor *vendor, GncTaxTable *table)
608 : {
609 0 : if (!vendor) return;
610 0 : if (vendor->taxtable == table) return;
611 0 : gncVendorBeginEdit (vendor);
612 0 : if (vendor->taxtable)
613 0 : gncTaxTableDecRef (vendor->taxtable);
614 0 : if (table)
615 0 : gncTaxTableIncRef (table);
616 0 : vendor->taxtable = table;
617 0 : mark_vendor (vendor);
618 0 : gncVendorCommitEdit (vendor);
619 : }
620 :
621 : static void
622 1 : qofVendorSetAddr (GncVendor *vendor, QofInstance *addr_ent)
623 : {
624 : GncAddress *addr;
625 :
626 1 : if (!vendor || !addr_ent)
627 : {
628 0 : return;
629 : }
630 1 : addr = (GncAddress*)addr_ent;
631 1 : if (addr == vendor->addr)
632 : {
633 0 : return;
634 : }
635 1 : if (vendor->addr != NULL)
636 : {
637 1 : gncAddressBeginEdit(vendor->addr);
638 1 : gncAddressDestroy(vendor->addr);
639 : }
640 1 : gncVendorBeginEdit(vendor);
641 1 : vendor->addr = addr;
642 1 : gncVendorCommitEdit(vendor);
643 : }
644 :
645 : static void
646 1 : qofVendorSetTaxIncluded(GncVendor *vendor, const char* type_string)
647 : {
648 : GncTaxIncluded inc;
649 :
650 1 : if (!gncTaxIncludedStringToType(type_string, &inc))
651 : {
652 0 : return;
653 : }
654 1 : gncVendorBeginEdit(vendor);
655 1 : vendor->taxincluded = inc;
656 1 : gncVendorCommitEdit(vendor);
657 : }
658 :
659 : /* ============================================================== */
660 : /* Get Functions */
661 :
662 8 : const char * gncVendorGetID (const GncVendor *vendor)
663 : {
664 8 : if (!vendor) return NULL;
665 8 : return vendor->id;
666 : }
667 :
668 33 : const char * gncVendorGetName (const GncVendor *vendor)
669 : {
670 33 : if (!vendor) return NULL;
671 33 : return vendor->name;
672 : }
673 :
674 14 : GncAddress * gncVendorGetAddr (const GncVendor *vendor)
675 : {
676 14 : if (!vendor) return NULL;
677 14 : return vendor->addr;
678 : }
679 :
680 3 : const char * gncVendorGetNotes (const GncVendor *vendor)
681 : {
682 3 : if (!vendor) return NULL;
683 3 : return vendor->notes;
684 : }
685 :
686 5 : GncBillTerm * gncVendorGetTerms (const GncVendor *vendor)
687 : {
688 5 : if (!vendor) return 0;
689 5 : return vendor->terms;
690 : }
691 :
692 2 : GncTaxIncluded gncVendorGetTaxIncluded (const GncVendor *vendor)
693 : {
694 2 : if (!vendor) return GNC_TAXINCLUDED_USEGLOBAL;
695 2 : return vendor->taxincluded;
696 : }
697 :
698 3 : gnc_commodity * gncVendorGetCurrency (const GncVendor *vendor)
699 : {
700 3 : if (!vendor) return NULL;
701 3 : return vendor->currency;
702 : }
703 :
704 12 : gboolean gncVendorGetActive (const GncVendor *vendor)
705 : {
706 12 : if (!vendor) return FALSE;
707 12 : return vendor->active;
708 : }
709 :
710 2 : gboolean gncVendorGetTaxTableOverride (const GncVendor *vendor)
711 : {
712 2 : if (!vendor) return FALSE;
713 2 : return vendor->taxtable_override;
714 : }
715 :
716 5 : GncTaxTable* gncVendorGetTaxTable (const GncVendor *vendor)
717 : {
718 5 : if (!vendor) return NULL;
719 5 : return vendor->taxtable;
720 : }
721 :
722 : static const char*
723 1 : qofVendorGetTaxIncluded(const GncVendor *vendor)
724 : {
725 1 : return gncTaxIncludedTypeToString(vendor->taxincluded);
726 : }
727 :
728 : /* Note that JobList changes do not affect the "dirtiness" of the vendor */
729 2 : void gncVendorAddJob (GncVendor *vendor, GncJob *job)
730 : {
731 2 : if (!vendor) return;
732 2 : if (!job) return;
733 :
734 2 : if (g_list_index(vendor->jobs, job) == -1)
735 2 : vendor->jobs = g_list_insert_sorted (vendor->jobs, job,
736 : (GCompareFunc)gncJobCompare);
737 :
738 2 : qof_event_gen (&vendor->inst, QOF_EVENT_MODIFY, NULL);
739 : }
740 :
741 2 : void gncVendorRemoveJob (GncVendor *vendor, GncJob *job)
742 : {
743 : GList *node;
744 :
745 2 : if (!vendor) return;
746 2 : if (!job) return;
747 :
748 2 : node = g_list_find (vendor->jobs, job);
749 2 : if (!node)
750 : {
751 : /* PERR ("split not in account"); */
752 : }
753 : else
754 : {
755 2 : vendor->jobs = g_list_remove_link (vendor->jobs, node);
756 2 : g_list_free_1 (node);
757 : }
758 :
759 2 : qof_event_gen (&vendor->inst, QOF_EVENT_MODIFY, NULL);
760 : }
761 :
762 108 : void gncVendorBeginEdit (GncVendor *vendor)
763 : {
764 108 : qof_begin_edit(&vendor->inst);
765 108 : }
766 :
767 0 : static void gncVendorOnError (QofInstance *vendor, QofBackendError errcode)
768 : {
769 0 : PERR("Vendor QofBackend Failure: %d", errcode);
770 0 : gnc_engine_signal_commit_error( errcode );
771 0 : }
772 :
773 48 : static void gncVendorOnDone (QofInstance *inst)
774 : {
775 48 : GncVendor *vendor = (GncVendor *) inst;
776 48 : gncAddressClearDirty (vendor->addr);
777 48 : }
778 :
779 13 : static void vendor_free (QofInstance *inst)
780 : {
781 13 : GncVendor *vendor = (GncVendor *) inst;
782 13 : gncVendorFree (vendor);
783 13 : }
784 :
785 108 : void gncVendorCommitEdit (GncVendor *vendor)
786 : {
787 108 : if (!qof_commit_edit (QOF_INSTANCE(vendor))) return;
788 61 : qof_commit_edit_part2 (&vendor->inst, gncVendorOnError,
789 : gncVendorOnDone, vendor_free);
790 : }
791 :
792 : /* ============================================================== */
793 : /* Other functions */
794 :
795 0 : int gncVendorCompare (const GncVendor *a, const GncVendor *b)
796 : {
797 0 : if (!a && !b) return 0;
798 0 : if (!a && b) return 1;
799 0 : if (a && !b) return -1;
800 :
801 0 : return(strcmp(a->name, b->name));
802 : }
803 :
804 1 : gboolean gncVendorEqual(const GncVendor *a, const GncVendor *b)
805 : {
806 1 : if (a == NULL && b == NULL) return TRUE;
807 1 : if (a == NULL || b == NULL) return FALSE;
808 :
809 1 : g_return_val_if_fail(GNC_IS_VENDOR(a), FALSE);
810 1 : g_return_val_if_fail(GNC_IS_VENDOR(b), FALSE);
811 :
812 1 : if (g_strcmp0(a->id, b->id) != 0)
813 : {
814 0 : PWARN("IDs differ: %s vs %s", a->id, b->id);
815 0 : return FALSE;
816 : }
817 :
818 1 : if (g_strcmp0(a->name, b->name) != 0)
819 : {
820 0 : PWARN("Names differ: %s vs %s", a->name, b->name);
821 0 : return FALSE;
822 : }
823 :
824 1 : if (g_strcmp0(a->notes, b->notes) != 0)
825 : {
826 0 : PWARN("Notes differ");
827 0 : return FALSE;
828 : }
829 :
830 1 : if (!gncBillTermEqual(a->terms, b->terms))
831 : {
832 0 : PWARN("BillTerms differ");
833 0 : return FALSE;
834 : }
835 :
836 1 : if (!gncAddressEqual(a->addr, b->addr))
837 : {
838 0 : PWARN("Addresses differ");
839 0 : return FALSE;
840 : }
841 :
842 1 : if (!gnc_commodity_equal(a->currency, b->currency))
843 : {
844 0 : PWARN("Currencies differ");
845 0 : return FALSE;
846 : }
847 :
848 1 : if (!gncTaxTableEqual(a->taxtable, b->taxtable))
849 : {
850 0 : PWARN("Tax tables differ");
851 0 : return FALSE;
852 : }
853 :
854 1 : if (a->taxtable_override != b->taxtable_override)
855 : {
856 0 : PWARN("Tax table override flags differ");
857 0 : return FALSE;
858 : }
859 :
860 1 : if (a->taxincluded != b->taxincluded)
861 : {
862 0 : PWARN("Tax included flags differ");
863 0 : return FALSE;
864 : }
865 :
866 1 : if (a->active != b->active)
867 : {
868 0 : PWARN("Active flags differ");
869 0 : return FALSE;
870 : }
871 :
872 : // GList * jobs;
873 1 : return TRUE;
874 : }
875 :
876 : gboolean
877 8 : gncVendorIsDirty (const GncVendor *vendor)
878 : {
879 8 : if (!vendor) return FALSE;
880 8 : return (qof_instance_get_dirty_flag(vendor)
881 8 : || gncAddressIsDirty (vendor->addr));
882 : }
883 :
884 : /**
885 : * Listen for qof events.
886 : *
887 : * - If the address of a vendor has changed, mark the vendor as dirty.
888 : * - If a lot related to a vendor has changed, clear the vendor's
889 : * cached balance as it likely has become invalid.
890 : *
891 : * @param entity Entity for the event
892 : * @param event_type Event type
893 : * @param user_data User data registered with the handler
894 : * @param event_data Event data passed with the event.
895 : */
896 : static void
897 191857 : vend_handle_qof_events (QofInstance *entity, QofEventId event_type,
898 : gpointer user_data, gpointer event_data)
899 : {
900 : /* Handle address change events */
901 191857 : if ((GNC_IS_ADDRESS (entity) &&
902 54 : (event_type & QOF_EVENT_MODIFY) != 0))
903 : {
904 31 : if (GNC_IS_VENDOR (event_data))
905 : {
906 18 : GncVendor* vend = GNC_VENDOR (event_data);
907 18 : gncVendorBeginEdit (vend);
908 18 : mark_vendor (vend);
909 18 : gncVendorCommitEdit (vend);
910 : }
911 31 : return;
912 : }
913 :
914 : /* Handle lot change events */
915 191826 : if (GNC_IS_LOT (entity))
916 : {
917 343 : GNCLot *lot = GNC_LOT (entity);
918 : GncOwner lot_owner;
919 343 : const GncOwner *end_owner = NULL;
920 343 : GncInvoice *invoice = gncInvoiceGetInvoiceFromLot (lot);
921 :
922 : /* Determine the owner associated with the lot */
923 343 : if (invoice)
924 : /* Invoice lots */
925 210 : end_owner = gncOwnerGetEndOwner (gncInvoiceGetOwner (invoice));
926 133 : else if (gncOwnerGetOwnerFromLot (lot, &lot_owner))
927 : /* Pre-payment lots */
928 36 : end_owner = gncOwnerGetEndOwner (&lot_owner);
929 :
930 343 : if (gncOwnerGetType (end_owner) == GNC_OWNER_VENDOR)
931 : {
932 : /* Clear the cached balance */
933 44 : GncVendor* vend = gncOwnerGetVendor (end_owner);
934 44 : g_free (vend->balance);
935 44 : vend->balance = NULL;
936 : }
937 343 : return;
938 : }
939 : }
940 :
941 : /* ============================================================== */
942 : /* Package-Private functions */
943 :
944 1 : static const char * _gncVendorPrintable (gpointer item)
945 : {
946 1 : GncVendor *v = item;
947 1 : if (!item) return NULL;
948 1 : return v->name;
949 : }
950 :
951 : static void
952 9 : destroy_vendor_on_book_close(QofInstance *ent, gpointer data)
953 : {
954 9 : GncVendor* v = GNC_VENDOR(ent);
955 :
956 9 : gncVendorBeginEdit(v);
957 9 : gncVendorDestroy(v);
958 9 : }
959 :
960 : /** Handles book end - frees all vendors from the book
961 : *
962 : * @param book Book being closed
963 : */
964 : static void
965 180 : gnc_vendor_book_end(QofBook* book)
966 : {
967 : QofCollection *col;
968 :
969 180 : col = qof_book_get_collection(book, GNC_ID_VENDOR);
970 180 : qof_collection_foreach(col, destroy_vendor_on_book_close, NULL);
971 180 : }
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 84 : gboolean gncVendorRegister (void)
989 : {
990 : static QofParam params[] =
991 : {
992 : { VENDOR_ID, QOF_TYPE_NATURAL, (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 84 : qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncVendorCompare, params);
1016 :
1017 84 : return qof_object_register (&gncVendorDesc);
1018 : }
1019 :
1020 0 : gchar *gncVendorNextID (QofBook *book)
1021 : {
1022 0 : return qof_book_increment_and_format_counter (book, _GNC_MOD_NAME);
1023 : }
1024 :
1025 : const gnc_numeric*
1026 0 : gncVendorGetCachedBalance (GncVendor *vend)
1027 : {
1028 0 : return vend->balance;
1029 : }
1030 :
1031 0 : void gncVendorSetCachedBalance (GncVendor *vend, const gnc_numeric *new_bal)
1032 : {
1033 0 : if (!new_bal)
1034 : {
1035 0 : if (vend->balance)
1036 : {
1037 0 : g_free (vend->balance);
1038 0 : vend->balance = NULL;
1039 : }
1040 0 : return;
1041 : }
1042 :
1043 0 : if (!vend->balance)
1044 0 : vend->balance = g_new0 (gnc_numeric, 1);
1045 :
1046 0 : *vend->balance = *new_bal;
1047 : }
|