GnuCash  5.6-150-g038405b370+
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 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 
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 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 
113  g_return_if_fail(GNC_IS_JOB(object));
114 
115  job = GNC_JOB(object);
116  switch (prop_id)
117  {
118  case PROP_NAME:
119  g_value_set_string(value, job->name);
120  break;
121  case PROP_PDF_DIRNAME:
122  qof_instance_get_kvp (QOF_INSTANCE (job), value, 1, OWNER_EXPORT_PDF_DIRNAME);
123  break;
124  default:
125  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
126  break;
127  }
128 }
129 
130 static void
131 gnc_job_set_property (GObject *object,
132  guint prop_id,
133  const GValue *value,
134  GParamSpec *pspec)
135 {
136  GncJob *job;
137 
138  g_return_if_fail(GNC_IS_JOB(object));
139 
140  job = GNC_JOB(object);
141  g_assert (qof_instance_get_editlevel(job));
142 
143  switch (prop_id)
144  {
145  case PROP_NAME:
146  gncJobSetName(job, g_value_get_string(value));
147  break;
148  case PROP_PDF_DIRNAME:
149  qof_instance_set_kvp (QOF_INSTANCE (job), value, 1, OWNER_EXPORT_PDF_DIRNAME);
150  break;
151  default:
152  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
153  break;
154  }
155 }
156 
163 static GList*
164 impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
165 {
166  /* Refers to nothing */
167  return NULL;
168 }
169 
170 static void
171 gnc_job_class_init (GncJobClass *klass)
172 {
173  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
174  QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
175 
176  gobject_class->dispose = gnc_job_dispose;
177  gobject_class->finalize = gnc_job_finalize;
178  gobject_class->set_property = gnc_job_set_property;
179  gobject_class->get_property = gnc_job_get_property;
180 
181  qof_class->get_display_name = NULL;
182  qof_class->refers_to_object = NULL;
183  qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
184 
185  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  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 }
210 
211 /* Create/Destroy Functions */
212 GncJob *gncJobCreate (QofBook *book)
213 {
214  GncJob *job;
215 
216  if (!book) return NULL;
217 
218  job = g_object_new (GNC_TYPE_JOB, NULL);
219  qof_instance_init_data (&job->inst, _GNC_MOD_NAME, book);
220 
221  job->id = CACHE_INSERT ("");
222  job->name = CACHE_INSERT ("");
223  job->desc = CACHE_INSERT ("");
224  job->active = TRUE;
225 
226  /* GncOwner not initialized */
227  qof_event_gen (&job->inst, QOF_EVENT_CREATE, NULL);
228 
229  return job;
230 }
231 
232 static void free_job_list (GncJob *job)
233 {
234  gncJobBeginEdit (job);
235  gncJobDestroy (job);
236 }
237 
238 void gncJobFreeList (GList *jobs)
239 {
240  GList *job_list = g_list_copy (jobs);
241  g_list_free_full (job_list, (GDestroyNotify)free_job_list);
242 }
243 
244 void gncJobDestroy (GncJob *job)
245 {
246  if (!job) return;
247  qof_instance_set_destroying(job, TRUE);
248  gncJobCommitEdit (job);
249 }
250 
251 static void gncJobFree (GncJob *job)
252 {
253  if (!job) return;
254 
255  qof_event_gen (&job->inst, QOF_EVENT_DESTROY, NULL);
256 
257  CACHE_REMOVE (job->id);
258  CACHE_REMOVE (job->name);
259  CACHE_REMOVE (job->desc);
260 
261  switch (gncOwnerGetType (&(job->owner)))
262  {
263  case GNC_OWNER_CUSTOMER:
264  gncCustomerRemoveJob (gncOwnerGetCustomer(&job->owner), job);
265  break;
266  case GNC_OWNER_VENDOR:
267  gncVendorRemoveJob (gncOwnerGetVendor(&job->owner), job);
268  break;
269  default:
270  break;
271  }
272 
273  /* qof_instance_release (&job->inst); */
274  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 void gncJobSetID (GncJob *job, const char *id)
288 {
289  if (!job) return;
290  if (!id) return;
291  SET_STR(job, job->id, id);
292  mark_job (job);
293  gncJobCommitEdit (job);
294 }
295 
296 void gncJobSetName (GncJob *job, const char *name)
297 {
298  if (!job) return;
299  if (!name) return;
300  SET_STR(job, job->name, name);
301  mark_job (job);
302  gncJobCommitEdit (job);
303 }
304 
305 void gncJobSetReference (GncJob *job, const char *desc)
306 {
307  if (!job) return;
308  if (!desc) return;
309  SET_STR(job, job->desc, desc);
310  mark_job (job);
311  gncJobCommitEdit (job);
312 }
313 
314 void gncJobSetRate (GncJob *job, gnc_numeric rate)
315 {
316  if (!job) return;
317  if (gnc_numeric_equal (gncJobGetRate(job), rate)) return;
318 
319  gncJobBeginEdit (job);
320  if (!gnc_numeric_zero_p(rate))
321  {
322  GValue v = G_VALUE_INIT;
323  g_value_init (&v, GNC_TYPE_NUMERIC);
324  g_value_set_boxed (&v, &rate);
325  qof_instance_set_kvp (QOF_INSTANCE (job), &v, 1, GNC_JOB_RATE);
326  g_value_unset (&v);
327  }
328  else
329  {
330  qof_instance_set_kvp (QOF_INSTANCE (job), NULL, 1, GNC_JOB_RATE);
331  }
332  mark_job (job);
333  gncJobCommitEdit (job);
334 }
335 
336 void gncJobSetOwner (GncJob *job, GncOwner *owner)
337 {
338  if (!job) return;
339  if (!owner) return;
340  if (gncOwnerEqual (owner, &(job->owner))) return;
341 
342  switch (gncOwnerGetType (owner))
343  {
344  case GNC_OWNER_CUSTOMER:
345  case GNC_OWNER_VENDOR:
346  break;
347  default:
348  PERR("Unsupported Owner type: %d", gncOwnerGetType(owner));
349  return;
350  }
351 
352  gncJobBeginEdit (job);
353 
354  switch (gncOwnerGetType (&(job->owner)))
355  {
356  case GNC_OWNER_CUSTOMER:
357  gncCustomerRemoveJob (gncOwnerGetCustomer(&job->owner), job);
358  break;
359  case GNC_OWNER_VENDOR:
360  gncVendorRemoveJob (gncOwnerGetVendor(&job->owner), job);
361  break;
362  default:
363  break;
364  }
365 
366  gncOwnerCopy (owner, &(job->owner));
367 
368  switch (gncOwnerGetType (&(job->owner)))
369  {
370  case GNC_OWNER_CUSTOMER:
371  gncCustomerAddJob (gncOwnerGetCustomer(&job->owner), job);
372  break;
373  case GNC_OWNER_VENDOR:
374  gncVendorAddJob (gncOwnerGetVendor(&job->owner), job);
375  break;
376  default:
377  break;
378  }
379 
380  mark_job (job);
381  gncJobCommitEdit (job);
382 }
383 
384 void gncJobSetActive (GncJob *job, gboolean active)
385 {
386  if (!job) return;
387  if (active == job->active) return;
388  gncJobBeginEdit (job);
389  job->active = active;
390  mark_job (job);
391  gncJobCommitEdit (job);
392 }
393 
394 static void
395 qofJobSetOwner (GncJob *job, QofInstance *ent)
396 {
397  if (!job || !ent)
398  {
399  return;
400  }
401 
402  gncJobBeginEdit (job);
403  qofOwnerSetEntity(&job->owner, ent);
404  mark_job (job);
405  gncJobCommitEdit (job);
406 }
407 
408 void gncJobBeginEdit (GncJob *job)
409 {
410  qof_begin_edit(&job->inst);
411 }
412 
413 static void gncJobOnError (QofInstance *inst, QofBackendError errcode)
414 {
415  PERR("Job QofBackend Failure: %d", errcode);
416  gnc_engine_signal_commit_error( errcode );
417 }
418 
419 static void job_free (QofInstance *inst)
420 {
421  GncJob *job = (GncJob *)inst;
422  gncJobFree (job);
423 }
424 
425 static void gncJobOnDone (QofInstance *qof) { }
426 
427 void gncJobCommitEdit (GncJob *job)
428 {
429  /* GnuCash 2.6.3 and earlier didn't handle job kvp's... */
430  if (qof_instance_has_kvp (QOF_INSTANCE (job)))
431  gnc_features_set_used (qof_instance_get_book (QOF_INSTANCE (job)), GNC_FEATURE_KVP_EXTRA_DATA);
432 
433  if (!qof_commit_edit (QOF_INSTANCE(job))) return;
434  qof_commit_edit_part2 (&job->inst, gncJobOnError,
435  gncJobOnDone, job_free);
436 }
437 
438 /* ================================================================== */
439 /* Get Functions */
440 
441 const char * gncJobGetID (const GncJob *job)
442 {
443  if (!job) return NULL;
444  return job->id;
445 }
446 
447 const char * gncJobGetName (const GncJob *job)
448 {
449  if (!job) return NULL;
450  return job->name;
451 }
452 
453 const char * gncJobGetReference (const GncJob *job)
454 {
455  if (!job) return NULL;
456  return job->desc;
457 }
458 
459 gnc_numeric gncJobGetRate (const GncJob *job)
460 {
461  GValue v = G_VALUE_INIT;
462  gnc_numeric *rate = NULL;
463  gnc_numeric retval;
464  if (!job) return gnc_numeric_zero ();
465  qof_instance_get_kvp (QOF_INSTANCE (job), &v, 1, GNC_JOB_RATE);
466  if (G_VALUE_HOLDS_BOXED (&v))
467  rate = (gnc_numeric*)g_value_get_boxed (&v);
468  retval = rate ? *rate : gnc_numeric_zero ();
469  g_value_unset (&v);
470  return retval;
471 }
472 
473 GncOwner * gncJobGetOwner (GncJob *job)
474 {
475  if (!job) return NULL;
476  return &(job->owner);
477 }
478 
479 gboolean gncJobGetActive (const GncJob *job)
480 {
481  if (!job) return FALSE;
482  return job->active;
483 }
484 
485 static QofInstance*
486 qofJobGetOwner (GncJob *job)
487 {
488  if (!job)
489  {
490  return NULL;
491  }
492  return QOF_INSTANCE(qofOwnerGetOwner(&job->owner));
493 }
494 
495 /* Other functions */
496 
497 int gncJobCompare (const GncJob * a, const GncJob *b)
498 {
499  if (!a && !b) return 0;
500  if (!a && b) return 1;
501  if (a && !b) return -1;
502 
503  return (g_strcmp0(a->id, b->id));
504 }
505 
506 gboolean gncJobEqual(const GncJob * a, const GncJob *b)
507 {
508  if (a == NULL && b == NULL) return TRUE;
509  if (a == NULL || b == NULL) return FALSE;
510 
511  g_return_val_if_fail(GNC_IS_JOB(a), FALSE);
512  g_return_val_if_fail(GNC_IS_JOB(b), FALSE);
513 
514  if (g_strcmp0(a->id, b->id) != 0)
515  {
516  PWARN("IDs differ: %s vs %s", a->id, b->id);
517  return FALSE;
518  }
519 
520  if (g_strcmp0(a->name, b->name) != 0)
521  {
522  PWARN("Names differ: %s vs %s", a->name, b->name);
523  return FALSE;
524  }
525 
526  if (g_strcmp0(a->desc, b->desc) != 0)
527  {
528  PWARN("Descriptions differ: %s vs %s", a->desc, b->desc);
529  return FALSE;
530  }
531 
532  if (!gnc_numeric_equal(gncJobGetRate(a), gncJobGetRate(b)))
533  {
534  PWARN("Rates differ");
535  return FALSE;
536  }
537 
538  if (a->active != b->active)
539  {
540  PWARN("Active flags differ");
541  return FALSE;
542  }
543 
544  /* FIXME: Need real tests */
545 #if 0
546  GncOwner owner;
547 #endif
548 
549  return TRUE;
550 }
551 
552 /* ================================================================== */
553 /* Package-Private functions */
554 
555 static const char * _gncJobPrintable (gpointer item)
556 {
557  GncJob *c;
558  if (!item) return NULL;
559  c = item;
560  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 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  qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncJobCompare, params);
595  qofJobGetOwner(NULL);
596  qofJobSetOwner(NULL, NULL);
597  return qof_object_register (&gncJobDesc);
598 }
599 
600 gchar *gncJobNextID (QofBook *book)
601 {
602  return qof_book_increment_and_format_counter (book, _GNC_MOD_NAME);
603 }
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
Compare two instances, based on their last update times.
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b represent the same number.
Definition: qof.py:1
const GncGUID * qof_instance_get_guid(gconstpointer inst)
Return the GncGUID of this instance.
void qof_instance_set_kvp(QofInstance *, GValue const *value, unsigned count,...)
Sets a KVP slot to a value from a GValue.
QofBook * qof_instance_get_book(gconstpointer inst)
Return the book pointer.
gboolean qof_collection_is_dirty(const QofCollection *col)
Return value of &#39;dirty&#39; flag on collection.
Definition: qofid.cpp:255
QofBackendError
The errors that can be reported to the GUI & other front-end users.
Definition: qofbackend.h:57
gchar * qof_book_increment_and_format_counter(QofBook *book, const char *counter_name)
This will increment the named counter for this book and format it.
Definition: qofbook.cpp:625
void gnc_features_set_used(QofBook *book, const gchar *feature)
Indicate that the current book uses the given feature.
void qof_class_register(QofIdTypeConst obj_name, QofSortFunc default_sort_function, const QofParam *params)
This function registers a new object class with the Qof subsystem.
Definition: qofclass.cpp:86
gboolean gncOwnerEqual(const GncOwner *a, const GncOwner *b)
Assess equality by checking.
Definition: gncOwner.c:404
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
int(* QofSortFunc)(gconstpointer, gconstpointer)
This function is the default sort function for a particular object type.
Definition: qofclass.h:223
#define QOF_OBJECT_VERSION
Defines the version of the core object object registration interface.
Definition: qofobject.h:63
gboolean qof_commit_edit(QofInstance *inst)
commit_edit helpers
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
#define QOF_PARAM_BOOK
"Known" Object Parameters – all objects must support these
Definition: qofquery.h:108
void(* QofSetterFunc)(gpointer, gpointer)
The QofSetterFunc defines an function pointer for parameter setters.
Definition: qofclass.h:185
void qof_instance_get_kvp(QofInstance *, GValue *value, unsigned count,...)
Retrieves the contents of a KVP slot into a provided GValue.
QofInstance * qofOwnerGetOwner(const GncOwner *owner)
return the owner itself as an entity.
Definition: gncOwner.c:275
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
void qof_instance_init_data(QofInstance *inst, QofIdType type, QofBook *book)
Initialise the settings associated with an instance.
gboolean qof_begin_edit(QofInstance *inst)
begin_edit
Definition: gncJob.c:41
void qofOwnerSetEntity(GncOwner *owner, QofInstance *ent)
set the owner from the entity.
Definition: gncOwner.c:319
gboolean qof_commit_edit_part2(QofInstance *inst, void(*on_error)(QofInstance *, QofBackendError), void(*on_done)(QofInstance *), void(*on_free)(QofInstance *))
part2 – deal with the backend
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
The QofAccessFunc defines an arbitrary function pointer for access functions.
Definition: qofclass.h:178
void qof_collection_mark_clean(QofCollection *)
reset value of dirty flag
Definition: qofid.cpp:261
GncOwnerType gncOwnerGetType(const GncOwner *owner)
Returns the GncOwnerType of this owner.
Definition: gncOwner.c:200
Business Invoice Interface.
Job Interface.
GncVendor * gncOwnerGetVendor(const GncOwner *owner)
If the given owner is of type GNC_OWNER_VENDOR, returns the pointer to the vendor object...
Definition: gncOwner.c:383
GncCustomer * gncOwnerGetCustomer(const GncOwner *owner)
If the given owner is of type GNC_OWNER_CUSTOMER, returns the pointer to the customer object...
Definition: gncOwner.c:369
gboolean qof_object_register(const QofObject *object)
Register new types of object objects.
Definition: qofobject.cpp:299
gboolean qof_instance_has_kvp(QofInstance *inst)
Report whether a QofInstance has anything stored in KVP.
void qof_event_gen(QofInstance *entity, QofEventId event_id, gpointer event_data)
Invoke all registered event handlers using the given arguments.
Definition: qofevent.cpp:231
Utility functions for file access.