Branch data 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 : 48 : void mark_job (GncJob *job)
66 : : {
67 : 48 : qof_instance_set_dirty(&job->inst);
68 : 48 : qof_event_gen (&job->inst, QOF_EVENT_MODIFY, NULL);
69 : 48 : }
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 : 48 : G_DEFINE_TYPE(GncJob, gnc_job, QOF_TYPE_INSTANCE)
87 : :
88 : : static void
89 : 22 : gnc_job_init(GncJob* job)
90 : : {
91 : 22 : }
92 : :
93 : : static void
94 : 12 : gnc_job_dispose(GObject *jobp)
95 : : {
96 : 12 : G_OBJECT_CLASS(gnc_job_parent_class)->dispose(jobp);
97 : 12 : }
98 : :
99 : : static void
100 : 12 : gnc_job_finalize(GObject* jobp)
101 : : {
102 : 12 : G_OBJECT_CLASS(gnc_job_parent_class)->finalize(jobp);
103 : 12 : }
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 : 8 : gnc_job_class_init (GncJobClass *klass)
172 : : {
173 : 8 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
174 : 8 : QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
175 : :
176 : 8 : gobject_class->dispose = gnc_job_dispose;
177 : 8 : gobject_class->finalize = gnc_job_finalize;
178 : 8 : gobject_class->set_property = gnc_job_set_property;
179 : 8 : gobject_class->get_property = gnc_job_get_property;
180 : :
181 : 8 : qof_class->get_display_name = NULL;
182 : 8 : qof_class->refers_to_object = NULL;
183 : 8 : qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
184 : :
185 : 8 : 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 : 8 : 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 : 8 : }
210 : :
211 : : /* Create/Destroy Functions */
212 : 23 : GncJob *gncJobCreate (QofBook *book)
213 : : {
214 : : GncJob *job;
215 : :
216 : 23 : if (!book) return NULL;
217 : :
218 : 22 : job = g_object_new (GNC_TYPE_JOB, NULL);
219 : 22 : qof_instance_init_data (&job->inst, _GNC_MOD_NAME, book);
220 : :
221 : 22 : job->id = CACHE_INSERT ("");
222 : 22 : job->name = CACHE_INSERT ("");
223 : 22 : job->desc = CACHE_INSERT ("");
224 : 22 : job->active = TRUE;
225 : :
226 : : /* GncOwner not initialized */
227 : 22 : qof_event_gen (&job->inst, QOF_EVENT_CREATE, NULL);
228 : :
229 : 22 : 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 : 33 : void gncJobFreeList (GList *jobs)
239 : : {
240 : 33 : GList *job_list = g_list_copy (jobs);
241 : 33 : g_list_free_full (job_list, (GDestroyNotify)free_job_list);
242 : 33 : }
243 : :
244 : 11 : void gncJobDestroy (GncJob *job)
245 : : {
246 : 11 : if (!job) return;
247 : 11 : qof_instance_set_destroying(job, TRUE);
248 : 11 : gncJobCommitEdit (job);
249 : : }
250 : :
251 : 11 : static void gncJobFree (GncJob *job)
252 : : {
253 : 11 : if (!job) return;
254 : :
255 : 11 : qof_event_gen (&job->inst, QOF_EVENT_DESTROY, NULL);
256 : :
257 : 11 : CACHE_REMOVE (job->id);
258 : 11 : CACHE_REMOVE (job->name);
259 : 11 : CACHE_REMOVE (job->desc);
260 : :
261 : 11 : 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 : 7 : default:
270 : 7 : break;
271 : : }
272 : :
273 : : /* qof_instance_release (&job->inst); */
274 : 11 : 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 : 14 : void gncJobSetID (GncJob *job, const char *id)
288 : : {
289 : 14 : if (!job) return;
290 : 14 : if (!id) return;
291 : 14 : SET_STR(job, job->id, id);
292 : 14 : mark_job (job);
293 : 14 : gncJobCommitEdit (job);
294 : : }
295 : :
296 : 10 : void gncJobSetName (GncJob *job, const char *name)
297 : : {
298 : 10 : if (!job) return;
299 : 10 : if (!name) return;
300 : 10 : SET_STR(job, job->name, name);
301 : 10 : mark_job (job);
302 : 10 : 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 : 14 : void gncJobSetOwner (GncJob *job, GncOwner *owner)
337 : : {
338 : 14 : if (!job) return;
339 : 14 : if (!owner) return;
340 : 14 : if (gncOwnerEqual (owner, &(job->owner))) return;
341 : :
342 : 14 : switch (gncOwnerGetType (owner))
343 : : {
344 : 14 : case GNC_OWNER_CUSTOMER:
345 : : case GNC_OWNER_VENDOR:
346 : 14 : break;
347 : 0 : default:
348 : 0 : PERR("Unsupported Owner type: %d", gncOwnerGetType(owner));
349 : 0 : return;
350 : : }
351 : :
352 : 14 : gncJobBeginEdit (job);
353 : :
354 : 14 : 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 : 14 : default:
363 : 14 : break;
364 : : }
365 : :
366 : 14 : gncOwnerCopy (owner, &(job->owner));
367 : :
368 : 14 : switch (gncOwnerGetType (&(job->owner)))
369 : : {
370 : 12 : case GNC_OWNER_CUSTOMER:
371 : 12 : gncCustomerAddJob (gncOwnerGetCustomer(&job->owner), job);
372 : 12 : 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 : 14 : mark_job (job);
381 : 14 : 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 : 84 : qofJobSetOwner (GncJob *job, QofInstance *ent)
396 : : {
397 : 84 : if (!job || !ent)
398 : : {
399 : 84 : 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 : 65 : void gncJobBeginEdit (GncJob *job)
409 : : {
410 : 65 : qof_begin_edit(&job->inst);
411 : 65 : }
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 : 11 : static void job_free (QofInstance *inst)
420 : : {
421 : 11 : GncJob *job = (GncJob *)inst;
422 : 11 : gncJobFree (job);
423 : 11 : }
424 : :
425 : 44 : static void gncJobOnDone (QofInstance *qof) { }
426 : :
427 : 65 : void gncJobCommitEdit (GncJob *job)
428 : : {
429 : : /* GnuCash 2.6.3 and earlier didn't handle job kvp's... */
430 : 65 : 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 : 65 : if (!qof_commit_edit (QOF_INSTANCE(job))) return;
434 : 55 : qof_commit_edit_part2 (&job->inst, gncJobOnError,
435 : : gncJobOnDone, job_free);
436 : : }
437 : :
438 : : /* ================================================================== */
439 : : /* Get Functions */
440 : :
441 : 30 : const char * gncJobGetID (const GncJob *job)
442 : : {
443 : 30 : if (!job) return NULL;
444 : 6 : 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 : 129 : GncOwner * gncJobGetOwner (GncJob *job)
474 : : {
475 : 129 : if (!job) return NULL;
476 : 129 : 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 : 84 : qofJobGetOwner (GncJob *job)
487 : : {
488 : 84 : if (!job)
489 : : {
490 : 84 : 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 : 84 : 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 : 84 : qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncJobCompare, params);
595 : 84 : qofJobGetOwner(NULL);
596 : 84 : qofJobSetOwner(NULL, NULL);
597 : 84 : 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 : : }
|