Line data Source code
1 : /********************************************************************\
2 : * gncOrder.c -- the Core Business Order *
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 : * Author: Derek Atkins <warlord@MIT.EDU>
26 : */
27 :
28 : #include <config.h>
29 :
30 : #include <glib.h>
31 : #include <glib/gi18n.h>
32 : #include <qofinstance-p.h>
33 : #include <stdint.h>
34 :
35 : #include "gncEntry.h"
36 : #include "gncEntryP.h"
37 : #include "gncOrder.h"
38 : #include "gncOrderP.h"
39 : #include "gncOwner.h"
40 : #include "gncOwnerP.h"
41 :
42 : struct _gncOrder
43 : {
44 : QofInstance inst;
45 :
46 : const char * id;
47 : const char * notes;
48 : gboolean active;
49 :
50 : const char * reference;
51 : char * printname;
52 : GncOwner owner;
53 : GList * entries;
54 : time64 opened;
55 : time64 closed;
56 : };
57 :
58 : struct _gncOrderClass
59 : {
60 : QofInstanceClass parent_class;
61 : };
62 :
63 : static QofLogModule log_module = GNC_MOD_BUSINESS;
64 :
65 : #define _GNC_MOD_NAME GNC_ID_ORDER
66 :
67 : #define SET_STR(obj, member, str) { \
68 : if (!g_strcmp0 (member, str)) return; \
69 : gncOrderBeginEdit (obj); \
70 : CACHE_REPLACE (member, str); \
71 : }
72 :
73 : static inline void mark_order (GncOrder *order);
74 55 : void mark_order (GncOrder *order)
75 : {
76 55 : qof_instance_set_dirty(&order->inst);
77 55 : qof_event_gen (&order->inst, QOF_EVENT_MODIFY, NULL);
78 55 : }
79 :
80 : /* =============================================================== */
81 :
82 : enum
83 : {
84 : PROP_0,
85 : PROP_ID, /* Table */
86 : PROP_NOTES, /* Table */
87 : PROP_REFERENCE, /* Table */
88 : PROP_ACTIVE, /* Table */
89 : PROP_DATE_OPENED, /* Table */
90 : PROP_DATE_CLOSED, /* Table */
91 : // PROP_OWNER_TYPE, /* Table */
92 : // PROP_OWNER, /* Table */
93 : };
94 :
95 : /* GObject Initialization */
96 11 : G_DEFINE_TYPE(GncOrder, gnc_order, QOF_TYPE_INSTANCE)
97 :
98 : static void
99 5 : gnc_order_init(GncOrder* order)
100 : {
101 5 : order->closed = INT64_MAX;
102 5 : }
103 :
104 : static void
105 0 : gnc_order_dispose(GObject *orderp)
106 : {
107 0 : G_OBJECT_CLASS(gnc_order_parent_class)->dispose(orderp);
108 0 : }
109 :
110 : static void
111 0 : gnc_order_finalize(GObject* orderp)
112 : {
113 0 : G_OBJECT_CLASS(gnc_order_parent_class)->dispose(orderp);
114 0 : }
115 :
116 : static void
117 0 : gnc_order_get_property (GObject *object,
118 : guint prop_id,
119 : GValue *value,
120 : GParamSpec *pspec)
121 : {
122 : GncOrder *priv;
123 :
124 0 : g_return_if_fail(GNC_IS_ORDER(object));
125 :
126 0 : priv = GNC_ORDER(object);
127 0 : switch (prop_id)
128 : {
129 0 : case PROP_ID:
130 0 : g_value_set_string(value, priv->id);
131 0 : break;
132 0 : case PROP_NOTES:
133 0 : g_value_set_string(value, priv->notes);
134 0 : break;
135 0 : case PROP_ACTIVE:
136 0 : g_value_set_boolean(value, priv->active);
137 0 : break;
138 0 : case PROP_DATE_OPENED:
139 0 : g_value_set_boxed(value, &priv->opened);
140 0 : break;
141 0 : case PROP_DATE_CLOSED:
142 0 : g_value_set_boxed(value, &priv->closed);
143 0 : break;
144 0 : case PROP_REFERENCE:
145 0 : g_value_set_string(value, priv->reference);
146 0 : break;
147 0 : default:
148 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
149 0 : break;
150 : }
151 : }
152 :
153 : static void
154 0 : gnc_order_set_property (GObject *object,
155 : guint prop_id,
156 : const GValue *value,
157 : GParamSpec *pspec)
158 : {
159 : GncOrder *order;
160 :
161 0 : g_return_if_fail(GNC_IS_ORDER(object));
162 :
163 0 : order = GNC_ORDER(object);
164 0 : g_assert (qof_instance_get_editlevel(order));
165 :
166 0 : switch (prop_id)
167 : {
168 0 : case PROP_ID:
169 0 : gncOrderSetID(order, g_value_get_string(value));
170 0 : break;
171 0 : case PROP_NOTES:
172 0 : gncOrderSetNotes(order, g_value_get_string(value));
173 0 : break;
174 0 : case PROP_ACTIVE:
175 0 : gncOrderSetActive(order, g_value_get_boolean(value));
176 0 : break;
177 0 : case PROP_DATE_OPENED:
178 0 : gncOrderSetDateOpened(order, g_value_get_int64(value));
179 0 : break;
180 0 : case PROP_DATE_CLOSED:
181 0 : gncOrderSetDateClosed(order, g_value_get_int64(value));
182 0 : break;
183 0 : case PROP_REFERENCE:
184 0 : gncOrderSetReference(order, g_value_get_string(value));
185 0 : break;
186 0 : default:
187 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
188 0 : break;
189 : }
190 : }
191 :
192 : /** Returns a list of my type of object which refers to an object. For example, when called as
193 : qof_instance_get_typed_referring_object_list(taxtable, account);
194 : it will return the list of taxtables which refer to a specific account. The result should be the
195 : same regardless of which taxtable object is used. The list must be freed by the caller but the
196 : objects on the list must not.
197 : */
198 : static GList*
199 0 : impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
200 : {
201 : /* Refers to nothing */
202 0 : return NULL;
203 : }
204 :
205 : static void
206 3 : gnc_order_class_init (GncOrderClass *klass)
207 : {
208 3 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
209 3 : QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
210 :
211 3 : gobject_class->dispose = gnc_order_dispose;
212 3 : gobject_class->finalize = gnc_order_finalize;
213 3 : gobject_class->set_property = gnc_order_set_property;
214 3 : gobject_class->get_property = gnc_order_get_property;
215 :
216 3 : qof_class->get_display_name = NULL;
217 3 : qof_class->refers_to_object = NULL;
218 3 : qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
219 :
220 3 : g_object_class_install_property
221 : (gobject_class,
222 : PROP_ID,
223 : g_param_spec_string ("id",
224 : "Order ID",
225 : "The order id is an arbitrary string "
226 : "assigned by the user to identify the order.",
227 : NULL,
228 : G_PARAM_READWRITE));
229 :
230 3 : g_object_class_install_property
231 : (gobject_class,
232 : PROP_NOTES,
233 : g_param_spec_string ("notes",
234 : "Order Notes",
235 : "The order notes is an arbitrary string "
236 : "assigned by the user to provide notes about "
237 : "this order.",
238 : NULL,
239 : G_PARAM_READWRITE));
240 :
241 3 : g_object_class_install_property
242 : (gobject_class,
243 : PROP_ACTIVE,
244 : g_param_spec_boolean ("active",
245 : "Active",
246 : "TRUE if the order is active. FALSE if inactive.",
247 : FALSE,
248 : G_PARAM_READWRITE));
249 :
250 3 : g_object_class_install_property
251 : (gobject_class,
252 : PROP_DATE_OPENED,
253 : g_param_spec_boxed("date-opened",
254 : "Date Opened",
255 : "The date the order was opened.",
256 : GNC_TYPE_TIME64,
257 : G_PARAM_READWRITE));
258 :
259 3 : g_object_class_install_property
260 : (gobject_class,
261 : PROP_DATE_CLOSED,
262 : g_param_spec_boxed("date-closed",
263 : "Date Closed",
264 : "The date the order was closed.",
265 : GNC_TYPE_TIME64,
266 : G_PARAM_READWRITE));
267 :
268 3 : g_object_class_install_property
269 : (gobject_class,
270 : PROP_REFERENCE,
271 : g_param_spec_string ("reference",
272 : "Order Reference",
273 : "The order reference is an arbitrary string "
274 : "assigned by the user to provide a reference for "
275 : "this order.",
276 : NULL,
277 : G_PARAM_READWRITE));
278 3 : }
279 :
280 : /* Create/Destroy Functions */
281 5 : GncOrder *gncOrderCreate (QofBook *book)
282 : {
283 : GncOrder *order;
284 :
285 5 : if (!book) return NULL;
286 :
287 5 : order = g_object_new (GNC_TYPE_ORDER, NULL);
288 5 : qof_instance_init_data (&order->inst, _GNC_MOD_NAME, book);
289 :
290 5 : order->id = CACHE_INSERT ("");
291 5 : order->notes = CACHE_INSERT ("");
292 5 : order->reference = CACHE_INSERT ("");
293 :
294 5 : order->active = TRUE;
295 :
296 5 : qof_event_gen (&order->inst, QOF_EVENT_CREATE, NULL);
297 :
298 5 : return order;
299 : }
300 :
301 0 : void gncOrderDestroy (GncOrder *order)
302 : {
303 0 : if (!order) return;
304 0 : qof_instance_set_destroying(order, TRUE);
305 0 : gncOrderCommitEdit (order);
306 : }
307 :
308 0 : static void gncOrderFree (GncOrder *order)
309 : {
310 0 : if (!order) return;
311 :
312 0 : qof_event_gen (&order->inst, QOF_EVENT_DESTROY, NULL);
313 :
314 0 : g_list_free (order->entries);
315 0 : CACHE_REMOVE (order->id);
316 0 : CACHE_REMOVE (order->notes);
317 0 : CACHE_REMOVE (order->reference);
318 :
319 0 : if (order->printname) g_free (order->printname);
320 :
321 : /* qof_instance_release (&order->inst); */
322 0 : g_object_unref (order);
323 : }
324 :
325 : /* =============================================================== */
326 : /* Set Functions */
327 :
328 5 : void gncOrderSetID (GncOrder *order, const char *id)
329 : {
330 5 : if (!order || !id) return;
331 5 : SET_STR (order, order->id, id);
332 5 : mark_order (order);
333 5 : gncOrderCommitEdit (order);
334 : }
335 :
336 5 : void gncOrderSetOwner (GncOrder *order, GncOwner *owner)
337 : {
338 5 : if (!order || !owner) return;
339 5 : if (gncOwnerEqual (&order->owner, owner)) return;
340 :
341 5 : gncOrderBeginEdit (order);
342 5 : gncOwnerCopy (owner, &order->owner);
343 5 : mark_order (order);
344 5 : gncOrderCommitEdit (order);
345 : }
346 :
347 0 : void gncOrderSetDateOpened (GncOrder *order, time64 date)
348 : {
349 0 : if (!order) return;
350 0 : if (order->opened == date) return;
351 0 : gncOrderBeginEdit (order);
352 0 : order->opened = date;
353 0 : mark_order (order);
354 0 : gncOrderCommitEdit (order);
355 : }
356 :
357 0 : void gncOrderSetDateClosed (GncOrder *order, time64 date)
358 : {
359 0 : if (!order) return;
360 0 : if (order->closed == date) return;
361 0 : gncOrderBeginEdit (order);
362 0 : order->closed = date;
363 0 : mark_order (order);
364 0 : gncOrderCommitEdit (order);
365 : }
366 :
367 0 : void gncOrderSetNotes (GncOrder *order, const char *notes)
368 : {
369 0 : if (!order || !notes) return;
370 0 : SET_STR (order, order->notes, notes);
371 0 : mark_order (order);
372 0 : gncOrderCommitEdit (order);
373 : }
374 :
375 5 : void gncOrderSetReference (GncOrder *order, const char *reference)
376 : {
377 5 : if (!order || !reference) return;
378 5 : SET_STR (order, order->reference, reference);
379 5 : mark_order (order);
380 5 : gncOrderCommitEdit (order);
381 : }
382 :
383 5 : void gncOrderSetActive (GncOrder *order, gboolean active)
384 : {
385 5 : if (!order) return;
386 5 : if (order->active == active) return;
387 0 : gncOrderBeginEdit (order);
388 0 : order->active = active;
389 0 : mark_order (order);
390 0 : gncOrderCommitEdit (order);
391 : }
392 :
393 : /* =============================================================== */
394 : /* Add an Entry to the Order */
395 40 : void gncOrderAddEntry (GncOrder *order, GncEntry *entry)
396 : {
397 : GncOrder *old;
398 :
399 40 : if (!order || !entry) return;
400 :
401 40 : old = gncEntryGetOrder (entry);
402 40 : if (old == order) return; /* I already own it */
403 40 : if (old) gncOrderRemoveEntry (old, entry);
404 :
405 40 : gncOrderBeginEdit (order);
406 40 : order->entries = g_list_insert_sorted (order->entries, entry,
407 : (GCompareFunc)gncEntryCompare);
408 :
409 : /* This will send out an event -- make sure we're attached */
410 40 : gncEntrySetOrder (entry, order);
411 40 : mark_order (order);
412 40 : gncOrderCommitEdit (order);
413 : }
414 :
415 0 : void gncOrderRemoveEntry (GncOrder *order, GncEntry *entry)
416 : {
417 0 : if (!order || !entry) return;
418 :
419 0 : gncOrderBeginEdit (order);
420 0 : gncEntrySetOrder (entry, NULL);
421 0 : order->entries = g_list_remove (order->entries, entry);
422 0 : mark_order (order);
423 0 : gncOrderCommitEdit (order);
424 : }
425 :
426 : /* Get Functions */
427 :
428 0 : const char * gncOrderGetID (const GncOrder *order)
429 : {
430 0 : if (!order) return NULL;
431 0 : return order->id;
432 : }
433 :
434 0 : GncOwner * gncOrderGetOwner (GncOrder *order)
435 : {
436 0 : if (!order) return NULL;
437 0 : return &order->owner;
438 : }
439 :
440 0 : time64 gncOrderGetDateOpened (const GncOrder *order)
441 : {
442 0 : if (!order) return INT64_MAX;
443 0 : return order->opened;
444 : }
445 :
446 0 : time64 gncOrderGetDateClosed (const GncOrder *order)
447 : {
448 0 : if (!order) return INT64_MAX;
449 0 : return order->closed;
450 : }
451 :
452 0 : const char * gncOrderGetNotes (const GncOrder *order)
453 : {
454 0 : if (!order) return NULL;
455 0 : return order->notes;
456 : }
457 :
458 24 : const char * gncOrderGetReference (const GncOrder *order)
459 : {
460 24 : if (!order) return NULL;
461 3 : return order->reference;
462 : }
463 :
464 0 : gboolean gncOrderGetActive (const GncOrder *order)
465 : {
466 0 : if (!order) return FALSE;
467 0 : return order->active;
468 : }
469 :
470 : /* Get the list Entries */
471 0 : GList * gncOrderGetEntries (GncOrder *order)
472 : {
473 0 : if (!order) return NULL;
474 0 : return order->entries;
475 : }
476 :
477 0 : gboolean gncOrderIsClosed (const GncOrder *order)
478 : {
479 0 : if (!order) return FALSE;
480 0 : if (order->closed != INT64_MAX) return TRUE;
481 0 : return FALSE;
482 : }
483 :
484 : /* =============================================================== */
485 :
486 55 : void gncOrderBeginEdit (GncOrder *order)
487 : {
488 55 : qof_begin_edit(&order->inst);
489 55 : }
490 :
491 0 : static void gncOrderOnError (QofInstance *order, QofBackendError errcode)
492 : {
493 0 : PERR("Order QofBackend Failure: %d", errcode);
494 0 : gnc_engine_signal_commit_error( errcode );
495 0 : }
496 :
497 55 : static void gncOrderOnDone (QofInstance *order) {}
498 :
499 0 : static void order_free (QofInstance *inst)
500 : {
501 0 : GncOrder *order = (GncOrder *) inst;
502 0 : gncOrderFree (order);
503 0 : }
504 :
505 55 : void gncOrderCommitEdit (GncOrder *order)
506 : {
507 55 : if (!qof_commit_edit (QOF_INSTANCE(order))) return;
508 55 : qof_commit_edit_part2 (&order->inst, gncOrderOnError,
509 : gncOrderOnDone, order_free);
510 : }
511 :
512 0 : int gncOrderCompare (const GncOrder *a, const GncOrder *b)
513 : {
514 : int compare;
515 :
516 0 : if (a == b) return 0;
517 0 : if (!a) return -1;
518 0 : if (!b) return 1;
519 :
520 0 : compare = g_strcmp0 (a->id, b->id);
521 0 : if (compare) return compare;
522 :
523 0 : if (a->opened != b->opened) return a->opened - b->opened;
524 0 : if (a->closed != b->closed) return a->closed - b->closed;
525 :
526 0 : return qof_instance_guid_compare(a, b);
527 : }
528 :
529 :
530 : /* =========================================================== */
531 : /* Package-Private functions */
532 :
533 : static const char *
534 0 : _gncOrderPrintable (gpointer obj)
535 : {
536 0 : GncOrder *order = obj;
537 :
538 0 : g_return_val_if_fail (order, NULL);
539 :
540 0 : if (qof_instance_get_dirty_flag(order) || order->printname == NULL)
541 : {
542 0 : if (order->printname) g_free (order->printname);
543 :
544 0 : order->printname =
545 0 : g_strdup_printf ("%s%s", order->id,
546 0 : gncOrderIsClosed (order) ? _(" (closed)") : "");
547 : }
548 :
549 0 : return order->printname;
550 : }
551 :
552 : static QofObject gncOrderDesc =
553 : {
554 : DI(.interface_version = ) QOF_OBJECT_VERSION,
555 : DI(.e_type = ) _GNC_MOD_NAME,
556 : DI(.type_label = ) "Order",
557 : DI(.create = ) (gpointer)gncOrderCreate,
558 : DI(.book_begin = ) NULL,
559 : DI(.book_end = ) NULL,
560 : DI(.is_dirty = ) qof_collection_is_dirty,
561 : DI(.mark_clean = ) qof_collection_mark_clean,
562 : DI(.foreach = ) qof_collection_foreach,
563 : DI(.printable = ) _gncOrderPrintable,
564 : DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
565 : };
566 :
567 83 : gboolean gncOrderRegister (void)
568 : {
569 : static QofParam params[] =
570 : {
571 : { ORDER_ID, QOF_TYPE_STRING, (QofAccessFunc)gncOrderGetID, (QofSetterFunc)gncOrderSetID },
572 : { ORDER_REFERENCE, QOF_TYPE_STRING, (QofAccessFunc)gncOrderGetReference, (QofSetterFunc)gncOrderSetReference },
573 : { ORDER_OWNER, GNC_ID_OWNER, (QofAccessFunc)gncOrderGetOwner, (QofSetterFunc)gncOrderSetOwner },
574 : { ORDER_OPENED, QOF_TYPE_DATE, (QofAccessFunc)gncOrderGetDateOpened, (QofSetterFunc)gncOrderSetDateOpened },
575 : { ORDER_IS_CLOSED, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncOrderIsClosed, NULL },
576 : { ORDER_CLOSED, QOF_TYPE_DATE, (QofAccessFunc)gncOrderGetDateClosed, (QofSetterFunc)gncOrderSetDateClosed },
577 : { ORDER_NOTES, QOF_TYPE_STRING, (QofAccessFunc)gncOrderGetNotes, (QofSetterFunc)gncOrderSetNotes },
578 : { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncOrderGetActive, (QofSetterFunc)gncOrderSetActive },
579 : { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
580 : { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
581 : { NULL },
582 : };
583 :
584 83 : qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncOrderCompare, params);
585 :
586 83 : return qof_object_register (&gncOrderDesc);
587 : }
588 :
589 0 : gchar *gncOrderNextID (QofBook *book)
590 : {
591 0 : return qof_book_increment_and_format_counter (book, _GNC_MOD_NAME);
592 : }
|