Line data Source code
1 : /********************************************************************\
2 : * gncJob.c -- the Core Job 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-features.h"
36 : #include "gncInvoice.h"
37 : #include "gncJob.h"
38 : #include "gncJobP.h"
39 : #include "gncOwnerP.h"
40 :
41 : struct _gncJob
42 : {
43 : QofInstance inst;
44 : const char * id;
45 : const char * name;
46 : const char * desc;
47 : GncOwner owner;
48 : gboolean active;
49 : };
50 :
51 : struct _gncJobClass
52 : {
53 : QofInstanceClass parent_class;
54 : };
55 :
56 : static QofLogModule log_module = GNC_MOD_BUSINESS;
57 :
58 : #define _GNC_MOD_NAME GNC_ID_JOB
59 : #define GNC_JOB_RATE "job-rate"
60 :
61 : /* ================================================================== */
62 : /* misc inline functions */
63 :
64 : static inline void mark_job (GncJob *job);
65 59 : void mark_job (GncJob *job)
66 : {
67 59 : qof_instance_set_dirty(&job->inst);
68 59 : qof_event_gen (&job->inst, QOF_EVENT_MODIFY, NULL);
69 59 : }
70 :
71 : /* ================================================================== */
72 :
73 : enum
74 : {
75 : PROP_0,
76 : // PROP_ID, /* Table */
77 : PROP_NAME, /* Table */
78 : // PROP_REFERENCE, /* Table */
79 : // PROP_ACTIVE, /* Table */
80 : // PROP_OWNER_TYPE, /* Table */
81 : // PROP_OWNER, /* Table */
82 : PROP_PDF_DIRNAME, /* KVP */
83 : };
84 :
85 : /* GObject Initialization */
86 60 : G_DEFINE_TYPE(GncJob, gnc_job, QOF_TYPE_INSTANCE)
87 :
88 : static void
89 30 : gnc_job_init(GncJob* job)
90 : {
91 30 : }
92 :
93 : static void
94 13 : gnc_job_dispose(GObject *jobp)
95 : {
96 13 : G_OBJECT_CLASS(gnc_job_parent_class)->dispose(jobp);
97 13 : }
98 :
99 : static void
100 13 : gnc_job_finalize(GObject* jobp)
101 : {
102 13 : G_OBJECT_CLASS(gnc_job_parent_class)->finalize(jobp);
103 13 : }
104 :
105 : static void
106 2 : gnc_job_get_property (GObject *object,
107 : guint prop_id,
108 : GValue *value,
109 : GParamSpec *pspec)
110 : {
111 : GncJob *job;
112 :
113 2 : g_return_if_fail(GNC_IS_JOB(object));
114 :
115 2 : job = GNC_JOB(object);
116 2 : switch (prop_id)
117 : {
118 1 : case PROP_NAME:
119 1 : g_value_set_string(value, job->name);
120 1 : break;
121 1 : case PROP_PDF_DIRNAME:
122 1 : qof_instance_get_kvp (QOF_INSTANCE (job), value, 1, OWNER_EXPORT_PDF_DIRNAME);
123 1 : break;
124 0 : default:
125 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
126 0 : break;
127 : }
128 : }
129 :
130 : static void
131 2 : gnc_job_set_property (GObject *object,
132 : guint prop_id,
133 : const GValue *value,
134 : GParamSpec *pspec)
135 : {
136 : GncJob *job;
137 :
138 2 : g_return_if_fail(GNC_IS_JOB(object));
139 :
140 2 : job = GNC_JOB(object);
141 2 : g_assert (qof_instance_get_editlevel(job));
142 :
143 2 : switch (prop_id)
144 : {
145 1 : case PROP_NAME:
146 1 : gncJobSetName(job, g_value_get_string(value));
147 1 : break;
148 1 : case PROP_PDF_DIRNAME:
149 1 : qof_instance_set_kvp (QOF_INSTANCE (job), value, 1, OWNER_EXPORT_PDF_DIRNAME);
150 1 : break;
151 0 : default:
152 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
153 0 : break;
154 : }
155 : }
156 :
157 : /** Returns a list of my type of object which refers to an object. For example, when called as
158 : qof_instance_get_typed_referring_object_list(taxtable, account);
159 : it will return the list of taxtables which refer to a specific account. The result should be the
160 : same regardless of which taxtable object is used. The list must be freed by the caller but the
161 : objects on the list must not.
162 : */
163 : static GList*
164 0 : impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
165 : {
166 : /* Refers to nothing */
167 0 : return NULL;
168 : }
169 :
170 : static void
171 10 : gnc_job_class_init (GncJobClass *klass)
172 : {
173 10 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
174 10 : QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
175 :
176 10 : gobject_class->dispose = gnc_job_dispose;
177 10 : gobject_class->finalize = gnc_job_finalize;
178 10 : gobject_class->set_property = gnc_job_set_property;
179 10 : gobject_class->get_property = gnc_job_get_property;
180 :
181 10 : qof_class->get_display_name = NULL;
182 10 : qof_class->refers_to_object = NULL;
183 10 : qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
184 :
185 10 : g_object_class_install_property
186 : (gobject_class,
187 : PROP_NAME,
188 : g_param_spec_string ("name",
189 : "Job Name",
190 : "The job name is an arbitrary string "
191 : "assigned by the user. It is intended to "
192 : "a short character string that is displayed "
193 : "by the GUI as the job mnemonic.",
194 : NULL,
195 : G_PARAM_READWRITE));
196 :
197 10 : g_object_class_install_property
198 : (gobject_class,
199 : PROP_PDF_DIRNAME,
200 : g_param_spec_string ("export-pdf-dir",
201 : "Export PDF Directory Name",
202 : "A subdirectory for exporting PDF reports which is "
203 : "appended to the target directory when writing them "
204 : "out. It is retrieved from preferences and stored on "
205 : "each 'Owner' object which prints items after "
206 : "printing.",
207 : NULL,
208 : G_PARAM_READWRITE));
209 10 : }
210 :
211 : /* Create/Destroy Functions */
212 31 : GncJob *gncJobCreate (QofBook *book)
213 : {
214 : GncJob *job;
215 :
216 31 : if (!book) return NULL;
217 :
218 30 : job = g_object_new (GNC_TYPE_JOB, NULL);
219 30 : qof_instance_init_data (&job->inst, _GNC_MOD_NAME, book);
220 :
221 30 : job->id = CACHE_INSERT ("");
222 30 : job->name = CACHE_INSERT ("");
223 30 : job->desc = CACHE_INSERT ("");
224 30 : job->active = TRUE;
225 :
226 : /* GncOwner not initialized */
227 30 : qof_event_gen (&job->inst, QOF_EVENT_CREATE, NULL);
228 :
229 30 : return job;
230 : }
231 :
232 3 : static void free_job_list (GncJob *job)
233 : {
234 3 : gncJobBeginEdit (job);
235 3 : gncJobDestroy (job);
236 3 : }
237 :
238 34 : void gncJobFreeList (GList *jobs)
239 : {
240 34 : GList *job_list = g_list_copy (jobs);
241 34 : g_list_free_full (job_list, (GDestroyNotify)free_job_list);
242 34 : }
243 :
244 12 : void gncJobDestroy (GncJob *job)
245 : {
246 12 : if (!job) return;
247 12 : qof_instance_set_destroying(job, TRUE);
248 12 : gncJobCommitEdit (job);
249 : }
250 :
251 12 : static void gncJobFree (GncJob *job)
252 : {
253 12 : if (!job) return;
254 :
255 12 : qof_event_gen (&job->inst, QOF_EVENT_DESTROY, NULL);
256 :
257 12 : CACHE_REMOVE (job->id);
258 12 : CACHE_REMOVE (job->name);
259 12 : CACHE_REMOVE (job->desc);
260 :
261 12 : switch (gncOwnerGetType (&(job->owner)))
262 : {
263 2 : case GNC_OWNER_CUSTOMER:
264 2 : gncCustomerRemoveJob (gncOwnerGetCustomer(&job->owner), job);
265 2 : break;
266 2 : case GNC_OWNER_VENDOR:
267 2 : gncVendorRemoveJob (gncOwnerGetVendor(&job->owner), job);
268 2 : break;
269 8 : default:
270 8 : break;
271 : }
272 :
273 : /* qof_instance_release (&job->inst); */
274 12 : g_object_unref (job);
275 : }
276 :
277 :
278 : /* ================================================================== */
279 : /* Set Functions */
280 :
281 : #define SET_STR(obj, member, str) { \
282 : if (!g_strcmp0 (member, str)) return; \
283 : gncJobBeginEdit (obj); \
284 : CACHE_REPLACE (member, str); \
285 : }
286 :
287 21 : void gncJobSetID (GncJob *job, const char *id)
288 : {
289 21 : if (!job) return;
290 21 : if (!id) return;
291 21 : SET_STR(job, job->id, id);
292 21 : mark_job (job);
293 21 : gncJobCommitEdit (job);
294 : }
295 :
296 11 : void gncJobSetName (GncJob *job, const char *name)
297 : {
298 11 : if (!job) return;
299 11 : if (!name) return;
300 11 : SET_STR(job, job->name, name);
301 11 : mark_job (job);
302 11 : gncJobCommitEdit (job);
303 : }
304 :
305 2 : void gncJobSetReference (GncJob *job, const char *desc)
306 : {
307 2 : if (!job) return;
308 2 : if (!desc) return;
309 2 : SET_STR(job, job->desc, desc);
310 1 : mark_job (job);
311 1 : gncJobCommitEdit (job);
312 : }
313 :
314 1 : void gncJobSetRate (GncJob *job, gnc_numeric rate)
315 : {
316 1 : if (!job) return;
317 1 : if (gnc_numeric_equal (gncJobGetRate(job), rate)) return;
318 :
319 1 : gncJobBeginEdit (job);
320 1 : if (!gnc_numeric_zero_p(rate))
321 : {
322 1 : GValue v = G_VALUE_INIT;
323 1 : g_value_init (&v, GNC_TYPE_NUMERIC);
324 1 : g_value_set_boxed (&v, &rate);
325 1 : qof_instance_set_kvp (QOF_INSTANCE (job), &v, 1, GNC_JOB_RATE);
326 1 : g_value_unset (&v);
327 : }
328 : else
329 : {
330 0 : qof_instance_set_kvp (QOF_INSTANCE (job), NULL, 1, GNC_JOB_RATE);
331 : }
332 1 : mark_job (job);
333 1 : gncJobCommitEdit (job);
334 : }
335 :
336 17 : void gncJobSetOwner (GncJob *job, GncOwner *owner)
337 : {
338 17 : if (!job) return;
339 17 : if (!owner) return;
340 17 : if (gncOwnerEqual (owner, &(job->owner))) return;
341 :
342 17 : switch (gncOwnerGetType (owner))
343 : {
344 17 : case GNC_OWNER_CUSTOMER:
345 : case GNC_OWNER_VENDOR:
346 17 : break;
347 0 : default:
348 0 : PERR("Unsupported Owner type: %d", gncOwnerGetType(owner));
349 0 : return;
350 : }
351 :
352 17 : gncJobBeginEdit (job);
353 :
354 17 : switch (gncOwnerGetType (&(job->owner)))
355 : {
356 0 : case GNC_OWNER_CUSTOMER:
357 0 : gncCustomerRemoveJob (gncOwnerGetCustomer(&job->owner), job);
358 0 : break;
359 0 : case GNC_OWNER_VENDOR:
360 0 : gncVendorRemoveJob (gncOwnerGetVendor(&job->owner), job);
361 0 : break;
362 17 : default:
363 17 : break;
364 : }
365 :
366 17 : gncOwnerCopy (owner, &(job->owner));
367 :
368 17 : switch (gncOwnerGetType (&(job->owner)))
369 : {
370 15 : case GNC_OWNER_CUSTOMER:
371 15 : gncCustomerAddJob (gncOwnerGetCustomer(&job->owner), job);
372 15 : break;
373 2 : case GNC_OWNER_VENDOR:
374 2 : gncVendorAddJob (gncOwnerGetVendor(&job->owner), job);
375 2 : break;
376 0 : default:
377 0 : break;
378 : }
379 :
380 17 : mark_job (job);
381 17 : gncJobCommitEdit (job);
382 : }
383 :
384 11 : void gncJobSetActive (GncJob *job, gboolean active)
385 : {
386 11 : if (!job) return;
387 11 : if (active == job->active) return;
388 8 : gncJobBeginEdit (job);
389 8 : job->active = active;
390 8 : mark_job (job);
391 8 : gncJobCommitEdit (job);
392 : }
393 :
394 : static void
395 86 : qofJobSetOwner (GncJob *job, QofInstance *ent)
396 : {
397 86 : if (!job || !ent)
398 : {
399 86 : return;
400 : }
401 :
402 0 : gncJobBeginEdit (job);
403 0 : qofOwnerSetEntity(&job->owner, ent);
404 0 : mark_job (job);
405 0 : gncJobCommitEdit (job);
406 : }
407 :
408 77 : void gncJobBeginEdit (GncJob *job)
409 : {
410 77 : qof_begin_edit(&job->inst);
411 77 : }
412 :
413 0 : static void gncJobOnError (QofInstance *inst, QofBackendError errcode)
414 : {
415 0 : PERR("Job QofBackend Failure: %d", errcode);
416 0 : gnc_engine_signal_commit_error( errcode );
417 0 : }
418 :
419 12 : static void job_free (QofInstance *inst)
420 : {
421 12 : GncJob *job = (GncJob *)inst;
422 12 : gncJobFree (job);
423 12 : }
424 :
425 55 : static void gncJobOnDone (QofInstance *qof) { }
426 :
427 77 : void gncJobCommitEdit (GncJob *job)
428 : {
429 : /* GnuCash 2.6.3 and earlier didn't handle job kvp's... */
430 77 : if (qof_instance_has_kvp (QOF_INSTANCE (job)))
431 4 : gnc_features_set_used (qof_instance_get_book (QOF_INSTANCE (job)), GNC_FEATURE_KVP_EXTRA_DATA);
432 :
433 77 : if (!qof_commit_edit (QOF_INSTANCE(job))) return;
434 67 : qof_commit_edit_part2 (&job->inst, gncJobOnError,
435 : gncJobOnDone, job_free);
436 : }
437 :
438 : /* ================================================================== */
439 : /* Get Functions */
440 :
441 48 : const char * gncJobGetID (const GncJob *job)
442 : {
443 48 : if (!job) return NULL;
444 24 : return job->id;
445 : }
446 :
447 33 : const char * gncJobGetName (const GncJob *job)
448 : {
449 33 : if (!job) return NULL;
450 9 : return job->name;
451 : }
452 :
453 2 : const char * gncJobGetReference (const GncJob *job)
454 : {
455 2 : if (!job) return NULL;
456 2 : return job->desc;
457 : }
458 :
459 2 : gnc_numeric gncJobGetRate (const GncJob *job)
460 : {
461 2 : GValue v = G_VALUE_INIT;
462 2 : gnc_numeric *rate = NULL;
463 : gnc_numeric retval;
464 2 : if (!job) return gnc_numeric_zero ();
465 2 : qof_instance_get_kvp (QOF_INSTANCE (job), &v, 1, GNC_JOB_RATE);
466 2 : if (G_VALUE_HOLDS_BOXED (&v))
467 1 : rate = (gnc_numeric*)g_value_get_boxed (&v);
468 2 : retval = rate ? *rate : gnc_numeric_zero ();
469 2 : g_value_unset (&v);
470 2 : return retval;
471 : }
472 :
473 136 : GncOwner * gncJobGetOwner (GncJob *job)
474 : {
475 136 : if (!job) return NULL;
476 136 : return &(job->owner);
477 : }
478 :
479 4 : gboolean gncJobGetActive (const GncJob *job)
480 : {
481 4 : if (!job) return FALSE;
482 4 : return job->active;
483 : }
484 :
485 : static QofInstance*
486 86 : qofJobGetOwner (GncJob *job)
487 : {
488 86 : if (!job)
489 : {
490 86 : return NULL;
491 : }
492 0 : return QOF_INSTANCE(qofOwnerGetOwner(&job->owner));
493 : }
494 :
495 : /* Other functions */
496 :
497 0 : int gncJobCompare (const GncJob * a, const GncJob *b)
498 : {
499 0 : if (!a && !b) return 0;
500 0 : if (!a && b) return 1;
501 0 : if (a && !b) return -1;
502 :
503 0 : return (g_strcmp0(a->id, b->id));
504 : }
505 :
506 0 : gboolean gncJobEqual(const GncJob * a, const GncJob *b)
507 : {
508 0 : if (a == NULL && b == NULL) return TRUE;
509 0 : if (a == NULL || b == NULL) return FALSE;
510 :
511 0 : g_return_val_if_fail(GNC_IS_JOB(a), FALSE);
512 0 : g_return_val_if_fail(GNC_IS_JOB(b), FALSE);
513 :
514 0 : if (g_strcmp0(a->id, b->id) != 0)
515 : {
516 0 : PWARN("IDs differ: %s vs %s", a->id, b->id);
517 0 : return FALSE;
518 : }
519 :
520 0 : if (g_strcmp0(a->name, b->name) != 0)
521 : {
522 0 : PWARN("Names differ: %s vs %s", a->name, b->name);
523 0 : return FALSE;
524 : }
525 :
526 0 : if (g_strcmp0(a->desc, b->desc) != 0)
527 : {
528 0 : PWARN("Descriptions differ: %s vs %s", a->desc, b->desc);
529 0 : return FALSE;
530 : }
531 :
532 0 : if (!gnc_numeric_equal(gncJobGetRate(a), gncJobGetRate(b)))
533 : {
534 0 : PWARN("Rates differ");
535 0 : return FALSE;
536 : }
537 :
538 0 : if (a->active != b->active)
539 : {
540 0 : PWARN("Active flags differ");
541 0 : return FALSE;
542 : }
543 :
544 : /* FIXME: Need real tests */
545 : #if 0
546 : GncOwner owner;
547 : #endif
548 :
549 0 : return TRUE;
550 : }
551 :
552 : /* ================================================================== */
553 : /* Package-Private functions */
554 :
555 1 : static const char * _gncJobPrintable (gpointer item)
556 : {
557 : GncJob *c;
558 1 : if (!item) return NULL;
559 1 : c = item;
560 1 : return c->name;
561 : }
562 :
563 : static QofObject gncJobDesc =
564 : {
565 : DI(.interface_version = ) QOF_OBJECT_VERSION,
566 : DI(.e_type = ) _GNC_MOD_NAME,
567 : DI(.type_label = ) "Job",
568 : DI(.create = ) (gpointer)gncJobCreate,
569 : DI(.book_begin = ) NULL,
570 : DI(.book_end = ) NULL,
571 : DI(.is_dirty = ) qof_collection_is_dirty,
572 : DI(.mark_clean = ) qof_collection_mark_clean,
573 : DI(.foreach = ) qof_collection_foreach,
574 : DI(.printable = ) _gncJobPrintable,
575 : DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
576 : };
577 :
578 86 : gboolean gncJobRegister (void)
579 : {
580 : static QofParam params[] =
581 : {
582 : { JOB_ID, QOF_TYPE_STRING, (QofAccessFunc)gncJobGetID, (QofSetterFunc)gncJobSetID },
583 : { JOB_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncJobGetName, (QofSetterFunc)gncJobSetName },
584 : { JOB_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncJobGetActive, (QofSetterFunc)gncJobSetActive },
585 : { JOB_REFERENCE, QOF_TYPE_STRING, (QofAccessFunc)gncJobGetReference, (QofSetterFunc)gncJobSetReference },
586 : { JOB_RATE, QOF_TYPE_NUMERIC, (QofAccessFunc)gncJobGetRate, (QofSetterFunc)gncJobSetRate },
587 : { JOB_OWNER, GNC_ID_OWNER, (QofAccessFunc)gncJobGetOwner, NULL },
588 : { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncJobGetActive, NULL },
589 : { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
590 : { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
591 : { NULL },
592 : };
593 :
594 86 : qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncJobCompare, params);
595 86 : qofJobGetOwner(NULL);
596 86 : qofJobSetOwner(NULL, NULL);
597 86 : return qof_object_register (&gncJobDesc);
598 : }
599 :
600 0 : gchar *gncJobNextID (QofBook *book)
601 : {
602 0 : return qof_book_increment_and_format_counter (book, _GNC_MOD_NAME);
603 : }
|