Branch data 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 : 70 : void mark_vendor (GncVendor *vendor)
83 : : {
84 : 70 : qof_instance_set_dirty(&vendor->inst);
85 : 70 : qof_event_gen (&vendor->inst, QOF_EVENT_MODIFY, NULL);
86 : 70 : }
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 : 154 : G_DEFINE_TYPE(GncVendor, gnc_vendor, QOF_TYPE_INSTANCE)
111 : :
112 : : static void
113 : 23 : gnc_vendor_init(GncVendor* vendor)
114 : : {
115 : 23 : }
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 : 7 : gnc_vendor_class_init (GncVendorClass *klass)
301 : : {
302 : 7 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
303 : 7 : QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
304 : :
305 : 7 : gobject_class->dispose = gnc_vendor_dispose;
306 : 7 : gobject_class->finalize = gnc_vendor_finalize;
307 : 7 : gobject_class->set_property = gnc_vendor_set_property;
308 : 7 : gobject_class->get_property = gnc_vendor_get_property;
309 : :
310 : 7 : qof_class->get_display_name = NULL;
311 : 7 : qof_class->refers_to_object = impl_refers_to_object;
312 : 7 : qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
313 : :
314 : 7 : 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 : 7 : 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 : 7 : 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 : 7 : 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 : 7 : 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 : 7 : 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 : 7 : 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 : 7 : 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 : 7 : 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 : 7 : 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 : 7 : 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 : 7 : 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 : 7 : 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 : 7 : 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 : 7 : }
451 : :
452 : : /* Create/Destroy Functions */
453 : 24 : GncVendor *gncVendorCreate (QofBook *book)
454 : : {
455 : : GncVendor *vendor;
456 : :
457 : 24 : if (!book) return NULL;
458 : :
459 : 23 : vendor = g_object_new (GNC_TYPE_VENDOR, NULL);
460 : 23 : qof_instance_init_data (&vendor->inst, _GNC_MOD_NAME, book);
461 : :
462 : 23 : vendor->id = CACHE_INSERT ("");
463 : 23 : vendor->name = CACHE_INSERT ("");
464 : 23 : vendor->notes = CACHE_INSERT ("");
465 : 23 : vendor->addr = gncAddressCreate (book, &vendor->inst);
466 : 23 : vendor->taxincluded = GNC_TAXINCLUDED_USEGLOBAL;
467 : 23 : vendor->active = TRUE;
468 : 23 : vendor->jobs = NULL;
469 : 23 : vendor->balance = NULL;
470 : :
471 : 23 : if (vend_qof_event_handler_id == 0)
472 : 7 : vend_qof_event_handler_id = qof_event_register_handler (vend_handle_qof_events, NULL);
473 : :
474 : 23 : qof_event_gen (&vendor->inst, QOF_EVENT_CREATE, NULL);
475 : :
476 : 23 : 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 : 14 : void gncVendorSetID (GncVendor *vendor, const char *id)
524 : : {
525 : 14 : if (!vendor) return;
526 : 14 : if (!id) return;
527 : 14 : SET_STR(vendor, vendor->id, id);
528 : 14 : mark_vendor (vendor);
529 : 14 : gncVendorCommitEdit (vendor);
530 : : }
531 : :
532 : 10 : void gncVendorSetName (GncVendor *vendor, const char *name)
533 : : {
534 : 10 : if (!vendor) return;
535 : 10 : if (!name) return;
536 : 10 : SET_STR(vendor, vendor->name, name);
537 : 10 : mark_vendor (vendor);
538 : 10 : gncVendorCommitEdit (vendor);
539 : : }
540 : :
541 : 6 : void gncVendorSetNotes (GncVendor *vendor, const char *notes)
542 : : {
543 : 6 : if (!vendor) return;
544 : 6 : if (!notes) return;
545 : 6 : SET_STR(vendor, vendor->notes, notes);
546 : 5 : mark_vendor (vendor);
547 : 5 : 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 : 7 : void gncVendorSetTaxIncluded (GncVendor *vendor, GncTaxIncluded taxincl)
566 : : {
567 : 7 : if (!vendor) return;
568 : 7 : if (taxincl == vendor->taxincluded) return;
569 : 4 : gncVendorBeginEdit (vendor);
570 : 4 : vendor->taxincluded = taxincl;
571 : 4 : mark_vendor (vendor);
572 : 4 : gncVendorCommitEdit (vendor);
573 : : }
574 : :
575 : 13 : void gncVendorSetCurrency (GncVendor *vendor, gnc_commodity *currency)
576 : : {
577 : 13 : if (!vendor || !currency) return;
578 : 13 : if (vendor->currency &&
579 : 0 : gnc_commodity_equal (vendor->currency, currency))
580 : 0 : return;
581 : 13 : gncVendorBeginEdit (vendor);
582 : 13 : vendor->currency = currency;
583 : 13 : mark_vendor (vendor);
584 : 13 : 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 : 31 : const char * gncVendorGetName (const GncVendor *vendor)
669 : : {
670 : 31 : if (!vendor) return NULL;
671 : 31 : 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 : 10 : gboolean gncVendorGetActive (const GncVendor *vendor)
705 : : {
706 : 10 : if (!vendor) return FALSE;
707 : 10 : 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 : 97 : void gncVendorBeginEdit (GncVendor *vendor)
763 : : {
764 : 97 : qof_begin_edit(&vendor->inst);
765 : 97 : }
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 : 41 : static void gncVendorOnDone (QofInstance *inst)
774 : : {
775 : 41 : GncVendor *vendor = (GncVendor *) inst;
776 : 41 : gncAddressClearDirty (vendor->addr);
777 : 41 : }
778 : :
779 : 13 : static void vendor_free (QofInstance *inst)
780 : : {
781 : 13 : GncVendor *vendor = (GncVendor *) inst;
782 : 13 : gncVendorFree (vendor);
783 : 13 : }
784 : :
785 : 97 : void gncVendorCommitEdit (GncVendor *vendor)
786 : : {
787 : 97 : if (!qof_commit_edit (QOF_INSTANCE(vendor))) return;
788 : 54 : 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 : 120655 : vend_handle_qof_events (QofInstance *entity, QofEventId event_type,
898 : : gpointer user_data, gpointer event_data)
899 : : {
900 : : /* Handle address change events */
901 : 120655 : if ((GNC_IS_ADDRESS (entity) &&
902 : 53 : (event_type & QOF_EVENT_MODIFY) != 0))
903 : : {
904 : 30 : 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 : 30 : return;
912 : : }
913 : :
914 : : /* Handle lot change events */
915 : 120625 : if (GNC_IS_LOT (entity))
916 : : {
917 : 253 : GNCLot *lot = GNC_LOT (entity);
918 : : GncOwner lot_owner;
919 : 253 : const GncOwner *end_owner = NULL;
920 : 253 : GncInvoice *invoice = gncInvoiceGetInvoiceFromLot (lot);
921 : :
922 : : /* Determine the owner associated with the lot */
923 : 253 : if (invoice)
924 : : /* Invoice lots */
925 : 164 : end_owner = gncOwnerGetEndOwner (gncInvoiceGetOwner (invoice));
926 : 89 : else if (gncOwnerGetOwnerFromLot (lot, &lot_owner))
927 : : /* Pre-payment lots */
928 : 24 : end_owner = gncOwnerGetEndOwner (&lot_owner);
929 : :
930 : 253 : if (gncOwnerGetType (end_owner) == GNC_OWNER_VENDOR)
931 : : {
932 : : /* Clear the cached balance */
933 : 36 : GncVendor* vend = gncOwnerGetVendor (end_owner);
934 : 36 : g_free (vend->balance);
935 : 36 : vend->balance = NULL;
936 : : }
937 : 253 : 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 : 154 : gnc_vendor_book_end(QofBook* book)
966 : : {
967 : : QofCollection *col;
968 : :
969 : 154 : col = qof_book_get_collection(book, GNC_ID_VENDOR);
970 : 154 : qof_collection_foreach(col, destroy_vendor_on_book_close, NULL);
971 : 154 : }
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 : 82 : gboolean gncVendorRegister (void)
989 : : {
990 : : static QofParam params[] =
991 : : {
992 : : { VENDOR_ID, QOF_TYPE_STRING, (QofAccessFunc)gncVendorGetID, (QofSetterFunc)gncVendorSetID },
993 : : { VENDOR_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncVendorGetName, (QofSetterFunc)gncVendorSetName },
994 : : { VENDOR_ADDR, GNC_ID_ADDRESS, (QofAccessFunc)gncVendorGetAddr, (QofSetterFunc)qofVendorSetAddr },
995 : : { VENDOR_NOTES, QOF_TYPE_STRING, (QofAccessFunc)gncVendorGetNotes, (QofSetterFunc)gncVendorSetNotes },
996 : : { VENDOR_TERMS, GNC_ID_BILLTERM, (QofAccessFunc)gncVendorGetTerms, (QofSetterFunc)gncVendorSetTerms },
997 : : {
998 : : VENDOR_TAX_OVERRIDE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncVendorGetTaxTableOverride,
999 : : (QofSetterFunc)gncVendorSetTaxTableOverride
1000 : : },
1001 : : {
1002 : : VENDOR_TAX_TABLE, GNC_ID_TAXTABLE, (QofAccessFunc)gncVendorGetTaxTable,
1003 : : (QofSetterFunc)gncVendorSetTaxTable
1004 : : },
1005 : : {
1006 : : VENDOR_TAX_INC, QOF_TYPE_STRING, (QofAccessFunc)qofVendorGetTaxIncluded,
1007 : : (QofSetterFunc)qofVendorSetTaxIncluded
1008 : : },
1009 : : { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
1010 : : { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
1011 : : { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncVendorGetActive, NULL },
1012 : : { NULL },
1013 : : };
1014 : :
1015 : 82 : qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncVendorCompare, params);
1016 : :
1017 : 82 : 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 : : }
|