GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gncJob.c
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 [email protected] *
20  * *
21 \********************************************************************/
22 
23 /*
24  * Copyright (C) 2001, 2002 Derek Atkins
25  * Copyright (C) 2003 Linas Vepstas <[email protected]>
26  * Author: Derek Atkins <[email protected]>
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  char * id;
45  char * name;
46  char * desc;
47  GncOwner owner;
48  gboolean active;
49 };
50 
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 G_INLINE_FUNC void mark_job (GncJob *job);
65 void mark_job (GncJob *job)
66 {
67  qof_instance_set_dirty(&job->inst);
68  qof_event_gen (&job->inst, QOF_EVENT_MODIFY, NULL);
69 }
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 G_DEFINE_TYPE(GncJob, gnc_job, QOF_TYPE_INSTANCE);
87 
88 static void
89 gnc_job_init(GncJob* job)
90 {
91 }
92 
93 static void
94 gnc_job_dispose(GObject *jobp)
95 {
96  G_OBJECT_CLASS(gnc_job_parent_class)->dispose(jobp);
97 }
98 
99 static void
100 gnc_job_finalize(GObject* jobp)
101 {
102  G_OBJECT_CLASS(gnc_job_parent_class)->finalize(jobp);
103 }
104 
105 static void
106 gnc_job_get_property (GObject *object,
107  guint prop_id,
108  GValue *value,
109  GParamSpec *pspec)
110 {
111  GncJob *job;
112  gchar *key;
113 
114  g_return_if_fail(GNC_IS_JOB(object));
115 
116  job = GNC_JOB(object);
117  switch (prop_id)
118  {
119  case PROP_NAME:
120  g_value_set_string(value, job->name);
121  break;
122  case PROP_PDF_DIRNAME:
123  key = OWNER_EXPORT_PDF_DIRNAME;
124  qof_instance_get_kvp (QOF_INSTANCE (job), key, value);
125  break;
126  default:
127  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
128  break;
129  }
130 }
131 
132 static void
133 gnc_job_set_property (GObject *object,
134  guint prop_id,
135  const GValue *value,
136  GParamSpec *pspec)
137 {
138  GncJob *job;
139  gchar *key;
140 
141  g_return_if_fail(GNC_IS_JOB(object));
142 
143  job = GNC_JOB(object);
144  g_assert (qof_instance_get_editlevel(job));
145 
146  switch (prop_id)
147  {
148  case PROP_NAME:
149  gncJobSetName(job, g_value_get_string(value));
150  break;
151  case PROP_PDF_DIRNAME:
152  key = OWNER_EXPORT_PDF_DIRNAME;
153  qof_instance_set_kvp (QOF_INSTANCE (job), key, value);
154  break;
155  default:
156  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
157  break;
158  }
159 }
160 
167 static GList*
168 impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
169 {
170  /* Refers to nothing */
171  return NULL;
172 }
173 
174 static void
175 gnc_job_class_init (GncJobClass *klass)
176 {
177  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
178  QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
179 
180  gobject_class->dispose = gnc_job_dispose;
181  gobject_class->finalize = gnc_job_finalize;
182  gobject_class->set_property = gnc_job_set_property;
183  gobject_class->get_property = gnc_job_get_property;
184 
185  qof_class->get_display_name = NULL;
186  qof_class->refers_to_object = NULL;
187  qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
188 
189  g_object_class_install_property
190  (gobject_class,
191  PROP_NAME,
192  g_param_spec_string ("name",
193  "Job Name",
194  "The job name is an arbitrary string "
195  "assigned by the user. It is intended to "
196  "a short character string that is displayed "
197  "by the GUI as the job mnemonic.",
198  NULL,
199  G_PARAM_READWRITE));
200 
201  g_object_class_install_property
202  (gobject_class,
203  PROP_PDF_DIRNAME,
204  g_param_spec_string ("export-pdf-dir",
205  "Export PDF Directory Name",
206  "A subdirectory for exporting PDF reports which is "
207  "appended to the target directory when writing them "
208  "out. It is retrieved from preferences and stored on "
209  "each 'Owner' object which prints items after "
210  "printing.",
211  NULL,
212  G_PARAM_READWRITE));
213 }
214 
215 /* Create/Destroy Functions */
216 GncJob *gncJobCreate (QofBook *book)
217 {
218  GncJob *job;
219 
220  if (!book) return NULL;
221 
222  job = g_object_new (GNC_TYPE_JOB, NULL);
223  qof_instance_init_data (&job->inst, _GNC_MOD_NAME, book);
224 
225  job->id = CACHE_INSERT ("");
226  job->name = CACHE_INSERT ("");
227  job->desc = CACHE_INSERT ("");
228  job->active = TRUE;
229 
230  /* GncOwner not initialized */
231  qof_event_gen (&job->inst, QOF_EVENT_CREATE, NULL);
232 
233  return job;
234 }
235 
236 void gncJobDestroy (GncJob *job)
237 {
238  if (!job) return;
239  qof_instance_set_destroying(job, TRUE);
240  gncJobCommitEdit (job);
241 }
242 
243 static void gncJobFree (GncJob *job)
244 {
245  if (!job) return;
246 
247  qof_event_gen (&job->inst, QOF_EVENT_DESTROY, NULL);
248 
249  CACHE_REMOVE (job->id);
250  CACHE_REMOVE (job->name);
251  CACHE_REMOVE (job->desc);
252 
253  switch (gncOwnerGetType (&(job->owner)))
254  {
255  case GNC_OWNER_CUSTOMER:
256  gncCustomerRemoveJob (gncOwnerGetCustomer(&job->owner), job);
257  break;
258  case GNC_OWNER_VENDOR:
259  gncVendorRemoveJob (gncOwnerGetVendor(&job->owner), job);
260  break;
261  default:
262  break;
263  }
264 
265  /* qof_instance_release (&job->inst); */
266  g_object_unref (job);
267 }
268 
269 
270 /* ================================================================== */
271 /* Set Functions */
272 
273 #define SET_STR(obj, member, str) { \
274  char * tmp; \
275  \
276  if (!g_strcmp0 (member, str)) return; \
277  gncJobBeginEdit (obj); \
278  tmp = CACHE_INSERT (str); \
279  CACHE_REMOVE (member); \
280  member = tmp; \
281  }
282 
283 void gncJobSetID (GncJob *job, const char *id)
284 {
285  if (!job) return;
286  if (!id) return;
287  SET_STR(job, job->id, id);
288  mark_job (job);
289  gncJobCommitEdit (job);
290 }
291 
292 void gncJobSetName (GncJob *job, const char *name)
293 {
294  if (!job) return;
295  if (!name) return;
296  SET_STR(job, job->name, name);
297  mark_job (job);
298  gncJobCommitEdit (job);
299 }
300 
301 void gncJobSetReference (GncJob *job, const char *desc)
302 {
303  if (!job) return;
304  if (!desc) return;
305  SET_STR(job, job->desc, desc);
306  mark_job (job);
307  gncJobCommitEdit (job);
308 }
309 
310 void gncJobSetRate (GncJob *job, gnc_numeric rate)
311 {
312  if (!job) return;
313  if (gnc_numeric_equal (gncJobGetRate(job), rate)) return;
314 
315  gncJobBeginEdit (job);
316  if (!gnc_numeric_zero_p(rate))
317  kvp_frame_set_numeric(job->inst.kvp_data, GNC_JOB_RATE, rate);
318  else
319  {
320  KvpFrame *frame;
321  KvpValue *value;
322 
323  value = NULL;
324  frame = kvp_frame_set_value_nc (job->inst.kvp_data,
325  GNC_JOB_RATE, value);
326  if (!frame) kvp_value_delete (value);
327  }
328  mark_job (job);
329  gncJobCommitEdit (job);
330 }
331 
332 void gncJobSetOwner (GncJob *job, GncOwner *owner)
333 {
334  if (!job) return;
335  if (!owner) return;
336  if (gncOwnerEqual (owner, &(job->owner))) return;
337 
338  switch (gncOwnerGetType (owner))
339  {
340  case GNC_OWNER_CUSTOMER:
341  case GNC_OWNER_VENDOR:
342  break;
343  default:
344  PERR("Unsupported Owner type: %d", gncOwnerGetType(owner));
345  return;
346  }
347 
348  gncJobBeginEdit (job);
349 
350  switch (gncOwnerGetType (&(job->owner)))
351  {
352  case GNC_OWNER_CUSTOMER:
353  gncCustomerRemoveJob (gncOwnerGetCustomer(&job->owner), job);
354  break;
355  case GNC_OWNER_VENDOR:
356  gncVendorRemoveJob (gncOwnerGetVendor(&job->owner), job);
357  break;
358  default:
359  break;
360  }
361 
362  gncOwnerCopy (owner, &(job->owner));
363 
364  switch (gncOwnerGetType (&(job->owner)))
365  {
366  case GNC_OWNER_CUSTOMER:
367  gncCustomerAddJob (gncOwnerGetCustomer(&job->owner), job);
368  break;
369  case GNC_OWNER_VENDOR:
370  gncVendorAddJob (gncOwnerGetVendor(&job->owner), job);
371  break;
372  default:
373  break;
374  }
375 
376  mark_job (job);
377  gncJobCommitEdit (job);
378 }
379 
380 void gncJobSetActive (GncJob *job, gboolean active)
381 {
382  if (!job) return;
383  if (active == job->active) return;
384  gncJobBeginEdit (job);
385  job->active = active;
386  mark_job (job);
387  gncJobCommitEdit (job);
388 }
389 
390 static void
391 qofJobSetOwner (GncJob *job, QofInstance *ent)
392 {
393  if (!job || !ent)
394  {
395  return;
396  }
397 
398  gncJobBeginEdit (job);
399  qofOwnerSetEntity(&job->owner, ent);
400  mark_job (job);
401  gncJobCommitEdit (job);
402 }
403 
404 void gncJobBeginEdit (GncJob *job)
405 {
406  qof_begin_edit(&job->inst);
407 }
408 
409 static void gncJobOnError (QofInstance *inst, QofBackendError errcode)
410 {
411  PERR("Job QofBackend Failure: %d", errcode);
412  gnc_engine_signal_commit_error( errcode );
413 }
414 
415 static void job_free (QofInstance *inst)
416 {
417  GncJob *job = (GncJob *)inst;
418  gncJobFree (job);
419 }
420 
421 static void gncJobOnDone (QofInstance *qof) { }
422 
423 void gncJobCommitEdit (GncJob *job)
424 {
425  /* GnuCash 2.6.3 and earlier didn't handle job kvp's... */
426  if (!kvp_frame_is_empty (job->inst.kvp_data))
427  gnc_features_set_used (qof_instance_get_book (QOF_INSTANCE (job)), GNC_FEATURE_KVP_EXTRA_DATA);
428 
429  if (!qof_commit_edit (QOF_INSTANCE(job))) return;
430  qof_commit_edit_part2 (&job->inst, gncJobOnError,
431  gncJobOnDone, job_free);
432 }
433 
434 /* ================================================================== */
435 /* Get Functions */
436 
437 const char * gncJobGetID (const GncJob *job)
438 {
439  if (!job) return NULL;
440  return job->id;
441 }
442 
443 const char * gncJobGetName (const GncJob *job)
444 {
445  if (!job) return NULL;
446  return job->name;
447 }
448 
449 const char * gncJobGetReference (const GncJob *job)
450 {
451  if (!job) return NULL;
452  return job->desc;
453 }
454 
455 gnc_numeric gncJobGetRate (const GncJob *job)
456 {
457  if (!job) return gnc_numeric_zero ();
458  return kvp_frame_get_numeric(job->inst.kvp_data, GNC_JOB_RATE);
459 }
460 
461 GncOwner * gncJobGetOwner (GncJob *job)
462 {
463  if (!job) return NULL;
464  return &(job->owner);
465 }
466 
467 gboolean gncJobGetActive (const GncJob *job)
468 {
469  if (!job) return FALSE;
470  return job->active;
471 }
472 
473 static QofInstance*
474 qofJobGetOwner (GncJob *job)
475 {
476  if (!job)
477  {
478  return NULL;
479  }
480  return QOF_INSTANCE(qofOwnerGetOwner(&job->owner));
481 }
482 
483 /* Other functions */
484 
485 int gncJobCompare (const GncJob * a, const GncJob *b)
486 {
487  if (!a && !b) return 0;
488  if (!a && b) return 1;
489  if (a && !b) return -1;
490 
491  return (g_strcmp0(a->id, b->id));
492 }
493 
494 gboolean gncJobEqual(const GncJob * a, const GncJob *b)
495 {
496  if (a == NULL && b == NULL) return TRUE;
497  if (a == NULL || b == NULL) return FALSE;
498 
499  g_return_val_if_fail(GNC_IS_JOB(a), FALSE);
500  g_return_val_if_fail(GNC_IS_JOB(b), FALSE);
501 
502  if (g_strcmp0(a->id, b->id) != 0)
503  {
504  PWARN("IDs differ: %s vs %s", a->id, b->id);
505  return FALSE;
506  }
507 
508  if (g_strcmp0(a->name, b->name) != 0)
509  {
510  PWARN("Names differ: %s vs %s", a->name, b->name);
511  return FALSE;
512  }
513 
514  if (g_strcmp0(a->desc, b->desc) != 0)
515  {
516  PWARN("Descriptions differ: %s vs %s", a->desc, b->desc);
517  return FALSE;
518  }
519 
520  if (!gnc_numeric_equal(gncJobGetRate(a), gncJobGetRate(b)))
521  {
522  PWARN("Rates differ");
523  return FALSE;
524  }
525 
526  if (a->active != b->active)
527  {
528  PWARN("Active flags differ");
529  return FALSE;
530  }
531 
532  /* FIXME: Need real tests */
533 #if 0
534  GncOwner owner;
535 #endif
536 
537  return TRUE;
538 }
539 
540 /* ================================================================== */
541 /* Package-Private functions */
542 
543 static const char * _gncJobPrintable (gpointer item)
544 {
545  GncJob *c;
546  if (!item) return NULL;
547  c = item;
548  return c->name;
549 }
550 
551 static QofObject gncJobDesc =
552 {
553  DI(.interface_version = ) QOF_OBJECT_VERSION,
554  DI(.e_type = ) _GNC_MOD_NAME,
555  DI(.type_label = ) "Job",
556  DI(.create = ) (gpointer)gncJobCreate,
557  DI(.book_begin = ) NULL,
558  DI(.book_end = ) NULL,
559  DI(.is_dirty = ) qof_collection_is_dirty,
560  DI(.mark_clean = ) qof_collection_mark_clean,
561  DI(.foreach = ) qof_collection_foreach,
562  DI(.printable = ) _gncJobPrintable,
563  DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
564 };
565 
566 gboolean gncJobRegister (void)
567 {
568  static QofParam params[] =
569  {
570  { JOB_ID, QOF_TYPE_STRING, (QofAccessFunc)gncJobGetID, (QofSetterFunc)gncJobSetID },
571  { JOB_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncJobGetName, (QofSetterFunc)gncJobSetName },
572  { JOB_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncJobGetActive, (QofSetterFunc)gncJobSetActive },
573  { JOB_REFERENCE, QOF_TYPE_STRING, (QofAccessFunc)gncJobGetReference, (QofSetterFunc)gncJobSetReference },
574  { JOB_RATE, QOF_TYPE_NUMERIC, (QofAccessFunc)gncJobGetRate, (QofSetterFunc)gncJobSetRate },
575 #ifdef GNUCASH_MAJOR_VERSION
576  { JOB_OWNER, GNC_ID_OWNER, (QofAccessFunc)gncJobGetOwner, NULL },
577 #else
578  { JOB_OWNER, QOF_TYPE_CHOICE, (QofAccessFunc)qofJobGetOwner, (QofSetterFunc)qofJobSetOwner },
579 #endif
580  { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncJobGetActive, NULL },
581  { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
582  { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
583  { NULL },
584  };
585 
586  if (!qof_choice_create(GNC_ID_JOB))
587  {
588  return FALSE;
589  }
590  if (!qof_choice_add_class(GNC_ID_INVOICE, GNC_ID_JOB, INVOICE_OWNER))
591  {
592  return FALSE;
593  }
594 
595  qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncJobCompare, params);
596 #ifdef GNUCASH_MAJOR_VERSION
597  qofJobGetOwner(NULL);
598  qofJobSetOwner(NULL, NULL);
599 #endif
600  return qof_object_register (&gncJobDesc);
601 }
602 
603 gchar *gncJobNextID (QofBook *book)
604 {
605  return qof_book_increment_and_format_counter (book, _GNC_MOD_NAME);
606 }
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
const GncGUID * qof_instance_get_guid(gconstpointer)
QofBook * qof_instance_get_book(gconstpointer)
gboolean qof_collection_is_dirty(const QofCollection *col)
QofBackendError
The errors that can be reported to the GUI & other front-end users.
Definition: qofbackend.h:59
gboolean kvp_frame_is_empty(const KvpFrame *frame)
gchar * qof_book_increment_and_format_counter(QofBook *book, const char *counter_name)
void gnc_features_set_used(QofBook *book, const gchar *feature)
Definition: gnc-features.c:131
void qof_class_register(QofIdTypeConst obj_name, QofSortFunc default_sort_fcn, const QofParam *params)
gboolean gncOwnerEqual(const GncOwner *a, const GncOwner *b)
Definition: gncOwner.c:382
gboolean gnc_numeric_zero_p(gnc_numeric a)
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
Definition: qofclass.h:177
#define QOF_OBJECT_VERSION
Definition: qofobject.h:64
gboolean qof_commit_edit(QofInstance *inst)
#define PERR(format, args...)
Definition: qoflog.h:237
#define QOF_PARAM_BOOK
Definition: qofquery.h:109
void qof_collection_foreach(const QofCollection *, QofInstanceForeachCB, gpointer user_data)
QofInstance * qofOwnerGetOwner(const GncOwner *owner)
Definition: gncOwner.c:253
#define PWARN(format, args...)
Definition: qoflog.h:243
void qof_instance_init_data(QofInstance *, QofIdType, QofBook *)
gboolean qof_begin_edit(QofInstance *inst)
Definition: gncJob.c:41
gboolean qof_choice_create(char *type)
Set an object as using QOF_TYPE_CHOICE.
void qofOwnerSetEntity(GncOwner *owner, QofInstance *ent)
Definition: gncOwner.c:297
void kvp_frame_set_numeric(KvpFrame *frame, const gchar *path, gnc_numeric nval)
int(* QofSortFunc)(gconstpointer, gconstpointer)
Definition: qofclass.h:222
gboolean qof_commit_edit_part2(QofInstance *inst, void(*on_error)(QofInstance *, QofBackendError), void(*on_done)(QofInstance *), void(*on_free)(QofInstance *))
void qof_collection_mark_clean(QofCollection *)
KvpFrame * kvp_frame_set_value_nc(KvpFrame *frame, const gchar *path, KvpValue *value)
GncOwnerType gncOwnerGetType(const GncOwner *owner)
Definition: gncOwner.c:201
Business Invoice Interface.
Job Interface.
gboolean qof_choice_add_class(const char *choice, char *add, char *param_name)
Add the choices for this parameter to the object.
struct KvpFrameImpl KvpFrame
Definition: kvp_frame.h:76
void(* QofSetterFunc)(gpointer, gpointer)
Definition: qofclass.h:184
GncVendor * gncOwnerGetVendor(const GncOwner *owner)
Definition: gncOwner.c:361
GncCustomer * gncOwnerGetCustomer(const GncOwner *owner)
Definition: gncOwner.c:347
gboolean qof_object_register(const QofObject *object)
void kvp_value_delete(KvpValue *value)
void qof_event_gen(QofInstance *entity, QofEventId event_type, gpointer event_data)
Invoke all registered event handlers using the given arguments.
#define QOF_TYPE_CHOICE
Identify an object as containing a choice.
Definition: qofchoice.h:108
struct KvpValueImpl KvpValue
Definition: kvp_frame.h:80
const gchar * QofLogModule
Definition: qofid.h:89
Utility functions for file access.