Branch data 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 : 44 : void mark_order (GncOrder *order)
75 : : {
76 : 44 : qof_instance_set_dirty(&order->inst);
77 : 44 : qof_event_gen (&order->inst, QOF_EVENT_MODIFY, NULL);
78 : 44 : }
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 : 8 : G_DEFINE_TYPE(GncOrder, gnc_order, QOF_TYPE_INSTANCE)
97 : :
98 : : static void
99 : 4 : gnc_order_init(GncOrder* order)
100 : : {
101 : 4 : order->closed = INT64_MAX;
102 : 4 : }
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 : 2 : gnc_order_class_init (GncOrderClass *klass)
207 : : {
208 : 2 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
209 : 2 : QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
210 : :
211 : 2 : gobject_class->dispose = gnc_order_dispose;
212 : 2 : gobject_class->finalize = gnc_order_finalize;
213 : 2 : gobject_class->set_property = gnc_order_set_property;
214 : 2 : gobject_class->get_property = gnc_order_get_property;
215 : :
216 : 2 : qof_class->get_display_name = NULL;
217 : 2 : qof_class->refers_to_object = NULL;
218 : 2 : qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
219 : :
220 : 2 : 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 : 2 : 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 : 2 : 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 : 2 : 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 : 2 : 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 : 2 : 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 : 2 : }
279 : :
280 : : /* Create/Destroy Functions */
281 : 4 : GncOrder *gncOrderCreate (QofBook *book)
282 : : {
283 : : GncOrder *order;
284 : :
285 : 4 : if (!book) return NULL;
286 : :
287 : 4 : order = g_object_new (GNC_TYPE_ORDER, NULL);
288 : 4 : qof_instance_init_data (&order->inst, _GNC_MOD_NAME, book);
289 : :
290 : 4 : order->id = CACHE_INSERT ("");
291 : 4 : order->notes = CACHE_INSERT ("");
292 : 4 : order->reference = CACHE_INSERT ("");
293 : :
294 : 4 : order->active = TRUE;
295 : :
296 : 4 : qof_event_gen (&order->inst, QOF_EVENT_CREATE, NULL);
297 : :
298 : 4 : 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 : 4 : void gncOrderSetID (GncOrder *order, const char *id)
329 : : {
330 : 4 : if (!order || !id) return;
331 : 4 : SET_STR (order, order->id, id);
332 : 4 : mark_order (order);
333 : 4 : gncOrderCommitEdit (order);
334 : : }
335 : :
336 : 4 : void gncOrderSetOwner (GncOrder *order, GncOwner *owner)
337 : : {
338 : 4 : if (!order || !owner) return;
339 : 4 : if (gncOwnerEqual (&order->owner, owner)) return;
340 : :
341 : 4 : gncOrderBeginEdit (order);
342 : 4 : gncOwnerCopy (owner, &order->owner);
343 : 4 : mark_order (order);
344 : 4 : 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 : 4 : void gncOrderSetReference (GncOrder *order, const char *reference)
376 : : {
377 : 4 : if (!order || !reference) return;
378 : 4 : SET_STR (order, order->reference, reference);
379 : 4 : mark_order (order);
380 : 4 : gncOrderCommitEdit (order);
381 : : }
382 : :
383 : 4 : void gncOrderSetActive (GncOrder *order, gboolean active)
384 : : {
385 : 4 : if (!order) return;
386 : 4 : 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 : 32 : void gncOrderAddEntry (GncOrder *order, GncEntry *entry)
396 : : {
397 : : GncOrder *old;
398 : :
399 : 32 : if (!order || !entry) return;
400 : :
401 : 32 : old = gncEntryGetOrder (entry);
402 : 32 : if (old == order) return; /* I already own it */
403 : 32 : if (old) gncOrderRemoveEntry (old, entry);
404 : :
405 : 32 : gncOrderBeginEdit (order);
406 : 32 : 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 : 32 : gncEntrySetOrder (entry, order);
411 : 32 : mark_order (order);
412 : 32 : 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 : 44 : void gncOrderBeginEdit (GncOrder *order)
487 : : {
488 : 44 : qof_begin_edit(&order->inst);
489 : 44 : }
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 : 44 : 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 : 44 : void gncOrderCommitEdit (GncOrder *order)
506 : : {
507 : 44 : if (!qof_commit_edit (QOF_INSTANCE(order))) return;
508 : 44 : 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 : 81 : 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 : 81 : qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncOrderCompare, params);
585 : :
586 : 81 : 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 : : }
|