GnuCash  4.8a-132-gcdaeb421d+
gnc-lot.c
1 /********************************************************************\
2  * gnc-lot.c -- AR/AP invoices; inventory lots; stock lots *
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  * FILE:
24  * gnc-lot.c
25  *
26  * FUNCTION:
27  * Lots implement the fundamental conceptual idea behind invoices,
28  * inventory lots, and stock market investment lots. See the file
29  * src/doc/lots.txt for implementation overview.
30  *
31  * XXX Lots are not currently treated in a correct transactional
32  * manner. There's now a per-Lot dirty flag in the QofInstance, but
33  * this code still needs to emit the correct signals when a lot has
34  * changed. This is true both in the Scrub2.c and in
35  * src/gnome/dialog-lot-viewer.c
36  *
37  * HISTORY:
38  * Created by Linas Vepstas May 2002
39  * Copyright (c) 2002,2003 Linas Vepstas <linas@linas.org>
40  */
41 
42 #include <config.h>
43 
44 #include <glib.h>
45 #include <glib/gi18n.h>
46 #include <qofinstance-p.h>
47 
48 #include "Account.h"
49 #include "AccountP.h"
50 #include "gnc-lot.h"
51 #include "gnc-lot-p.h"
52 #include "cap-gains.h"
53 #include "Transaction.h"
54 #include "TransactionP.h"
55 #include "gncInvoice.h"
56 
57 /* This static indicates the debugging module that this .o belongs to. */
58 static QofLogModule log_module = GNC_MOD_LOT;
59 
60 struct gnc_lot_s
61 {
62  QofInstance inst;
63 };
64 
65 enum
66 {
67  PROP_0,
68 // PROP_ACCOUNT, /* Table */
69  PROP_IS_CLOSED, /* Table */
70 
71  PROP_INVOICE, /* KVP */
72  PROP_OWNER_TYPE, /* KVP */
73  PROP_OWNER_GUID, /* KVP */
74 
75  PROP_RUNTIME_0,
76  PROP_MARKER, /* Runtime */
77 };
78 
79 typedef struct GNCLotPrivate
80 {
81  /* Account to which this lot applies. All splits in the lot must
82  * belong to this account.
83  */
84  Account * account;
85 
86  /* List of splits that belong to this lot. */
87  SplitList *splits;
88 
89  char *title;
90  char *notes;
91 
92  GncInvoice *cached_invoice;
93  /* Handy cached value to indicate if lot is closed. */
94  /* If value is negative, then the cache is invalid. */
95  signed char is_closed;
96 #define LOT_CLOSED_UNKNOWN (-1)
97 
98  /* traversal marker, handy for preventing recursion */
99  unsigned char marker;
100 } GNCLotPrivate;
101 
102 #define GET_PRIVATE(o) \
103  ((GNCLotPrivate*)g_type_instance_get_private((GTypeInstance*)o, GNC_TYPE_LOT))
104 
105 #define gnc_lot_set_guid(L,G) qof_instance_set_guid(QOF_INSTANCE(L),&(G))
106 
107 /* ============================================================= */
108 
109 static char*
110 is_unset = "unset";
111 
112 /* GObject Initialization */
113 G_DEFINE_TYPE_WITH_PRIVATE(GNCLot, gnc_lot, QOF_TYPE_INSTANCE)
114 
115 static void
116 gnc_lot_init(GNCLot* lot)
117 {
118  GNCLotPrivate* priv;
119 
120  priv = GET_PRIVATE(lot);
121  priv->account = NULL;
122  priv->splits = NULL;
123  priv->cached_invoice = NULL;
124  priv->is_closed = LOT_CLOSED_UNKNOWN;
125  priv->title = is_unset;
126  priv->notes = is_unset;
127  priv->marker = 0;
128 }
129 
130 static void
131 gnc_lot_dispose(GObject *lotp)
132 {
133  G_OBJECT_CLASS(gnc_lot_parent_class)->dispose(lotp);
134 }
135 
136 static void
137 gnc_lot_finalize(GObject* lotp)
138 {
139  G_OBJECT_CLASS(gnc_lot_parent_class)->finalize(lotp);
140 }
141 
142 static void
143 gnc_lot_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
144 {
145  GNCLot* lot;
146  GNCLotPrivate* priv;
147  gchar *key;
148 
149  g_return_if_fail(GNC_IS_LOT(object));
150 
151  lot = GNC_LOT(object);
152  priv = GET_PRIVATE(lot);
153  switch (prop_id)
154  {
155  case PROP_IS_CLOSED:
156  g_value_set_int(value, priv->is_closed);
157  break;
158  case PROP_MARKER:
159  g_value_set_int(value, priv->marker);
160  break;
161  case PROP_INVOICE:
162  qof_instance_get_kvp (QOF_INSTANCE (lot), value, 2, GNC_INVOICE_ID, GNC_INVOICE_GUID);
163  break;
164  case PROP_OWNER_TYPE:
165  qof_instance_get_kvp (QOF_INSTANCE (lot), value, 2, GNC_OWNER_ID, GNC_OWNER_TYPE);
166  break;
167  case PROP_OWNER_GUID:
168  qof_instance_get_kvp (QOF_INSTANCE (lot), value, 2, GNC_OWNER_ID, GNC_OWNER_GUID);
169  break;
170  default:
171  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
172  break;
173  }
174 }
175 
176 static void
177 gnc_lot_set_property (GObject* object,
178  guint prop_id,
179  const GValue* value,
180  GParamSpec* pspec)
181 {
182  GNCLot* lot;
183  GNCLotPrivate* priv;
184  gchar *key = NULL;
185 
186  g_return_if_fail(GNC_IS_LOT(object));
187 
188  lot = GNC_LOT(object);
189  if (prop_id < PROP_RUNTIME_0)
190  g_assert (qof_instance_get_editlevel(lot));
191 
192  priv = GET_PRIVATE(lot);
193  switch (prop_id)
194  {
195  case PROP_IS_CLOSED:
196  priv->is_closed = g_value_get_int(value);
197  break;
198  case PROP_MARKER:
199  priv->marker = g_value_get_int(value);
200  break;
201  case PROP_INVOICE:
202  qof_instance_set_kvp (QOF_INSTANCE (lot), value, 2, GNC_INVOICE_ID, GNC_INVOICE_GUID);
203  break;
204  case PROP_OWNER_TYPE:
205  qof_instance_set_kvp (QOF_INSTANCE (lot), value, 2, GNC_OWNER_ID, GNC_OWNER_TYPE);
206  break;
207  case PROP_OWNER_GUID:
208  qof_instance_set_kvp (QOF_INSTANCE (lot), value, 2, GNC_OWNER_ID, GNC_OWNER_GUID);
209  break;
210  default:
211  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
212  break;
213  }
214 }
215 
216 static void
217 gnc_lot_class_init(GNCLotClass* klass)
218 {
219  GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
220 
221  gobject_class->dispose = gnc_lot_dispose;
222  gobject_class->finalize = gnc_lot_finalize;
223  gobject_class->get_property = gnc_lot_get_property;
224  gobject_class->set_property = gnc_lot_set_property;
225 
226  g_object_class_install_property(
227  gobject_class,
228  PROP_IS_CLOSED,
229  g_param_spec_int("is-closed",
230  "Is Lot Closed",
231  "Indication of whether this lot is open "
232  "or closed to further changes.",
233  -1, 1, 0,
234  G_PARAM_READWRITE));
235 
236  g_object_class_install_property(
237  gobject_class,
238  PROP_MARKER,
239  g_param_spec_int("marker",
240  "Lot marker",
241  "Ipsum Lorem",
242  0, G_MAXINT8, 0,
243  G_PARAM_READWRITE));
244 
245  g_object_class_install_property(
246  gobject_class,
247  PROP_INVOICE,
248  g_param_spec_boxed("invoice",
249  "Invoice attached to lot",
250  "Used by GncInvoice",
251  GNC_TYPE_GUID,
252  G_PARAM_READWRITE));
253 
254  g_object_class_install_property(
255  gobject_class,
256  PROP_OWNER_TYPE,
257  g_param_spec_int64("owner-type",
258  "Owning Entity Type of lot",
259  "Used by GncOwner",
260  0, G_MAXINT64, 0,
261  G_PARAM_READWRITE));
262 
263  g_object_class_install_property(
264  gobject_class,
265  PROP_OWNER_GUID,
266  g_param_spec_boxed("owner-guid",
267  "Owner attached to lot",
268  "Used by GncOwner",
269  GNC_TYPE_GUID,
270  G_PARAM_READWRITE));
271 }
272 
273 GNCLot *
274 gnc_lot_new (QofBook *book)
275 {
276  GNCLot *lot;
277  g_return_val_if_fail (book, NULL);
278 
279  lot = g_object_new (GNC_TYPE_LOT, NULL);
280  qof_instance_init_data(QOF_INSTANCE(lot), GNC_ID_LOT, book);
281  qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_CREATE, NULL);
282  return lot;
283 }
284 
285 static void
286 gnc_lot_free(GNCLot* lot)
287 {
288  GList *node;
289  GNCLotPrivate* priv;
290  if (!lot) return;
291 
292  ENTER ("(lot=%p)", lot);
293  qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_DESTROY, NULL);
294 
295  priv = GET_PRIVATE(lot);
296  for (node = priv->splits; node; node = node->next)
297  {
298  Split *s = node->data;
299  s->lot = NULL;
300  }
301  g_list_free (priv->splits);
302 
303  if (priv->account && !qof_instance_get_destroying(priv->account))
304  xaccAccountRemoveLot (priv->account, lot);
305 
306  if (priv->notes != is_unset)
307  g_free (priv->notes);
308 
309  if (priv->title != is_unset)
310  g_free (priv->title);
311 
312  priv->notes = NULL;
313  priv->title = NULL;
314  priv->account = NULL;
315  priv->is_closed = TRUE;
316  /* qof_instance_release (&lot->inst); */
317  g_object_unref (lot);
318 
319  LEAVE();
320 }
321 
322 void
323 gnc_lot_destroy (GNCLot *lot)
324 {
325  if (!lot) return;
326 
327  gnc_lot_begin_edit(lot);
328  qof_instance_set_destroying(lot, TRUE);
329  gnc_lot_commit_edit(lot);
330 }
331 
332 /* ============================================================= */
333 
334 void
335 gnc_lot_begin_edit (GNCLot *lot)
336 {
337  qof_begin_edit(QOF_INSTANCE(lot));
338 }
339 
340 static void commit_err (QofInstance *inst, QofBackendError errcode)
341 {
342  PERR ("Failed to commit: %d", errcode);
343  gnc_engine_signal_commit_error( errcode );
344 }
345 
346 static void lot_free(QofInstance* inst)
347 {
348  GNCLot* lot = GNC_LOT(inst);
349 
350  gnc_lot_free(lot);
351 }
352 
353 static void noop (QofInstance *inst) {}
354 
355 void
356 gnc_lot_commit_edit (GNCLot *lot)
357 {
358  if (!qof_commit_edit (QOF_INSTANCE(lot))) return;
359  qof_commit_edit_part2 (QOF_INSTANCE(lot), commit_err, noop, lot_free);
360 }
361 
362 /* ============================================================= */
363 
364 GNCLot *
365 gnc_lot_lookup (const GncGUID *guid, QofBook *book)
366 {
367  QofCollection *col;
368  if (!guid || !book) return NULL;
369  col = qof_book_get_collection (book, GNC_ID_LOT);
370  return (GNCLot *) qof_collection_lookup_entity (col, guid);
371 }
372 
373 QofBook *
374 gnc_lot_get_book (GNCLot *lot)
375 {
376  return qof_instance_get_book(QOF_INSTANCE(lot));
377 }
378 
379 /* ============================================================= */
380 
381 gboolean
382 gnc_lot_is_closed (GNCLot *lot)
383 {
384  GNCLotPrivate* priv;
385  if (!lot) return TRUE;
386  priv = GET_PRIVATE(lot);
387  if (0 > priv->is_closed) gnc_lot_get_balance (lot);
388  return priv->is_closed;
389 }
390 
391 Account *
392 gnc_lot_get_account (const GNCLot *lot)
393 {
394  GNCLotPrivate* priv;
395  if (!lot) return NULL;
396  priv = GET_PRIVATE(lot);
397  return priv->account;
398 }
399 
400 GncInvoice * gnc_lot_get_cached_invoice (const GNCLot *lot)
401 {
402  if (!lot) return NULL;
403  return GET_PRIVATE(lot)->cached_invoice;
404 }
405 
406 void
407 gnc_lot_set_cached_invoice(GNCLot* lot, GncInvoice *invoice)
408 {
409  if (!lot) return;
410  GET_PRIVATE(lot)->cached_invoice = invoice;
411 }
412 
413 void
414 gnc_lot_set_account(GNCLot* lot, Account* account)
415 {
416  if (lot != NULL)
417  {
418  GNCLotPrivate* priv;
419  priv = GET_PRIVATE(lot);
420  priv->account = account;
421  }
422 }
423 
424 void
426 {
427  GNCLotPrivate* priv;
428  if (lot != NULL)
429  {
430  priv = GET_PRIVATE(lot);
431  priv->is_closed = LOT_CLOSED_UNKNOWN;
432  }
433 }
434 
435 SplitList *
436 gnc_lot_get_split_list (const GNCLot *lot)
437 {
438  GNCLotPrivate* priv;
439  if (!lot) return NULL;
440  priv = GET_PRIVATE(lot);
441  return priv->splits;
442 }
443 
444 gint gnc_lot_count_splits (const GNCLot *lot)
445 {
446  GNCLotPrivate* priv;
447  if (!lot) return 0;
448  priv = GET_PRIVATE(lot);
449  return g_list_length (priv->splits);
450 }
451 
452 /* ============================================================== */
453 /* Hmm, we should probably inline these. */
454 
455 const char *
456 gnc_lot_get_title (const GNCLot *lot)
457 {
458  GNCLotPrivate* priv;
459  if (!lot) return NULL;
460  priv = GET_PRIVATE (lot);
461  if (priv->title == is_unset)
462  {
463  GNCLotPrivate* priv = GET_PRIVATE (lot);
464  GValue v = G_VALUE_INIT;
465  qof_instance_get_kvp (QOF_INSTANCE (lot), &v, 1, "title");
466  priv->title = G_VALUE_HOLDS_STRING (&v) ? g_value_dup_string (&v) : NULL;
467  g_value_unset (&v);
468  }
469  return priv->title;
470 }
471 
472 const char *
473 gnc_lot_get_notes (const GNCLot *lot)
474 {
475  GNCLotPrivate* priv;
476  if (!lot) return NULL;
477  priv = GET_PRIVATE (lot);
478  if (priv->notes == is_unset)
479  {
480  GValue v = G_VALUE_INIT;
481  qof_instance_get_kvp (QOF_INSTANCE (lot), &v, 1, "notes");
482  priv->notes = G_VALUE_HOLDS_STRING (&v) ? g_value_dup_string (&v) : NULL;
483  g_value_unset (&v);
484  }
485  return priv->notes;
486 }
487 
488 void
489 gnc_lot_set_title (GNCLot *lot, const char *str)
490 {
491  GValue v = G_VALUE_INIT;
492  GNCLotPrivate* priv;
493  if (!lot) return;
494  priv = GET_PRIVATE (lot);
495  if (priv->title != is_unset)
496  g_free (priv->title);
497 
498  qof_begin_edit(QOF_INSTANCE(lot));
499  g_value_init (&v, G_TYPE_STRING);
500  g_value_set_string (&v, str);
501  priv->title = g_strdup (str);
502  qof_instance_set_kvp (QOF_INSTANCE (lot), &v, 1, "title");
503  qof_instance_set_dirty(QOF_INSTANCE(lot));
504  gnc_lot_commit_edit(lot);
505  g_value_unset (&v);
506 }
507 
508 void
509 gnc_lot_set_notes (GNCLot *lot, const char *str)
510 {
511  GValue v = G_VALUE_INIT;
512  GNCLotPrivate* priv;
513  if (!lot) return;
514  priv = GET_PRIVATE (lot);
515  if (priv->notes != is_unset)
516  g_free (priv->notes);
517  qof_begin_edit(QOF_INSTANCE(lot));
518  g_value_init (&v, G_TYPE_STRING);
519  g_value_set_string (&v, str);
520  priv->notes = g_strdup (str);
521  qof_instance_set_kvp (QOF_INSTANCE (lot), &v, 1, "notes");
522  qof_instance_set_dirty(QOF_INSTANCE(lot));
523  gnc_lot_commit_edit(lot);
524  g_value_unset (&v);
525 }
526 
527 /* ============================================================= */
528 
529 gnc_numeric
530 gnc_lot_get_balance (GNCLot *lot)
531 {
532  GNCLotPrivate* priv;
533  GList *node;
534  gnc_numeric zero = gnc_numeric_zero();
535  gnc_numeric baln = zero;
536  if (!lot) return zero;
537 
538  priv = GET_PRIVATE(lot);
539  if (!priv->splits)
540  {
541  priv->is_closed = FALSE;
542  return zero;
543  }
544 
545  /* Sum over splits; because they all belong to same account
546  * they will have same denominator.
547  */
548  for (node = priv->splits; node; node = node->next)
549  {
550  Split *s = node->data;
551  gnc_numeric amt = xaccSplitGetAmount (s);
552  baln = gnc_numeric_add_fixed (baln, amt);
553  g_assert (gnc_numeric_check (baln) == GNC_ERROR_OK);
554  }
555 
556  /* cache a zero balance as a closed lot */
557  if (gnc_numeric_equal (baln, zero))
558  {
559  priv->is_closed = TRUE;
560  }
561  else
562  {
563  priv->is_closed = FALSE;
564  }
565 
566  return baln;
567 }
568 
569 /* ============================================================= */
570 
571 void
572 gnc_lot_get_balance_before (const GNCLot *lot, const Split *split,
573  gnc_numeric *amount, gnc_numeric *value)
574 {
575  GNCLotPrivate* priv;
576  GList *node;
577  gnc_numeric zero = gnc_numeric_zero();
578  gnc_numeric amt = zero;
579  gnc_numeric val = zero;
580 
581  *amount = amt;
582  *value = val;
583  if (lot == NULL) return;
584 
585  priv = GET_PRIVATE(lot);
586  if (priv->splits)
587  {
588  Transaction *ta, *tb;
589  const Split *target;
590  /* If this is a gains split, find the source of the gains and use
591  its transaction for the comparison. Gains splits are in separate
592  transactions that may sort after non-gains transactions. */
593  target = xaccSplitGetGainsSourceSplit (split);
594  if (target == NULL)
595  target = split;
596  tb = xaccSplitGetParent (target);
597  for (node = priv->splits; node; node = node->next)
598  {
599  Split *s = node->data;
600  Split *source = xaccSplitGetGainsSourceSplit (s);
601  if (source == NULL)
602  source = s;
603  ta = xaccSplitGetParent (source);
604  if ((ta == tb && source != target) ||
605  xaccTransOrder (ta, tb) < 0)
606  {
607  gnc_numeric tmpval = xaccSplitGetAmount (s);
608  amt = gnc_numeric_add_fixed (amt, tmpval);
609  tmpval = xaccSplitGetValue (s);
610  val = gnc_numeric_add_fixed (val, tmpval);
611  }
612  }
613  }
614 
615  *amount = amt;
616  *value = val;
617 }
618 
619 /* ============================================================= */
620 
621 void
622 gnc_lot_add_split (GNCLot *lot, Split *split)
623 {
624  GNCLotPrivate* priv;
625  Account * acc;
626  if (!lot || !split) return;
627  priv = GET_PRIVATE(lot);
628 
629  ENTER ("(lot=%p, split=%p) %s amt=%s val=%s", lot, split,
630  gnc_lot_get_title (lot),
631  gnc_num_dbg_to_string (split->amount),
632  gnc_num_dbg_to_string (split->value));
633  gnc_lot_begin_edit(lot);
634  acc = xaccSplitGetAccount (split);
635  qof_instance_set_dirty(QOF_INSTANCE(lot));
636  if (NULL == priv->account)
637  {
638  xaccAccountInsertLot (acc, lot);
639  }
640  else if (priv->account != acc)
641  {
642  PERR ("splits from different accounts cannot "
643  "be added to this lot!\n"
644  "\tlot account=\'%s\', split account=\'%s\'\n",
645  xaccAccountGetName(priv->account), xaccAccountGetName (acc));
646  gnc_lot_commit_edit(lot);
647  LEAVE("different accounts");
648  return;
649  }
650 
651  if (lot == split->lot)
652  {
653  gnc_lot_commit_edit(lot);
654  LEAVE("already in lot");
655  return; /* handle not-uncommon no-op */
656  }
657  if (split->lot)
658  {
659  gnc_lot_remove_split (split->lot, split);
660  }
661  xaccSplitSetLot(split, lot);
662 
663  priv->splits = g_list_append (priv->splits, split);
664 
665  /* for recomputation of is-closed */
666  priv->is_closed = LOT_CLOSED_UNKNOWN;
667  gnc_lot_commit_edit(lot);
668 
669  qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_MODIFY, NULL);
670  LEAVE("added to lot");
671 }
672 
673 void
674 gnc_lot_remove_split (GNCLot *lot, Split *split)
675 {
676  GNCLotPrivate* priv;
677  if (!lot || !split) return;
678  priv = GET_PRIVATE(lot);
679 
680  ENTER ("(lot=%p, split=%p)", lot, split);
681  gnc_lot_begin_edit(lot);
682  qof_instance_set_dirty(QOF_INSTANCE(lot));
683  priv->splits = g_list_remove (priv->splits, split);
684  xaccSplitSetLot(split, NULL);
685  priv->is_closed = LOT_CLOSED_UNKNOWN; /* force an is-closed computation */
686 
687  if (NULL == priv->splits)
688  {
689  xaccAccountRemoveLot (priv->account, lot);
690  priv->account = NULL;
691  }
692  gnc_lot_commit_edit(lot);
693  qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_MODIFY, NULL);
694  LEAVE("removed from lot");
695 }
696 
697 /* ============================================================== */
698 /* Utility function, get earliest split in lot */
699 
700 Split *
702 {
703  GNCLotPrivate* priv;
704  if (!lot) return NULL;
705  priv = GET_PRIVATE(lot);
706  if (! priv->splits) return NULL;
707  priv->splits = g_list_sort (priv->splits, (GCompareFunc) xaccSplitOrderDateOnly);
708  return priv->splits->data;
709 }
710 
711 /* Utility function, get latest split in lot */
712 Split *
714 {
715  GNCLotPrivate* priv;
716  SplitList *node;
717 
718  if (!lot) return NULL;
719  priv = GET_PRIVATE(lot);
720  if (! priv->splits) return NULL;
721  priv->splits = g_list_sort (priv->splits, (GCompareFunc) xaccSplitOrderDateOnly);
722 
723  for (node = priv->splits; node->next; node = node->next)
724  ;
725 
726  return node->data;
727 }
728 
729 /* ============================================================= */
730 
731 static void
732 destroy_lot_on_book_close(QofInstance *ent, gpointer data)
733 {
734  GNCLot* lot = GNC_LOT(ent);
735 
736  gnc_lot_destroy(lot);
737 }
738 
739 static void
740 gnc_lot_book_end(QofBook* book)
741 {
742  QofCollection *col;
743 
744  col = qof_book_get_collection(book, GNC_ID_LOT);
745  qof_collection_foreach(col, destroy_lot_on_book_close, NULL);
746 }
747 
748 #ifdef _MSC_VER
749 /* MSVC compiler doesn't have C99 "designated initializers"
750  * so we wrap them in a macro that is empty on MSVC. */
751 # define DI(x) /* */
752 #else
753 # define DI(x) x
754 #endif
755 static QofObject gncLotDesc =
756 {
757  DI(.interface_version = ) QOF_OBJECT_VERSION,
758  DI(.e_type = ) GNC_ID_LOT,
759  DI(.type_label = ) "Lot",
760  DI(.create = ) (gpointer)gnc_lot_new,
761  DI(.book_begin = ) NULL,
762  DI(.book_end = ) gnc_lot_book_end,
763  DI(.is_dirty = ) qof_collection_is_dirty,
764  DI(.mark_clean = ) qof_collection_mark_clean,
765  DI(.foreach = ) qof_collection_foreach,
766  DI(.printable = ) NULL,
767  DI(.version_cmp = ) (int (*)(gpointer, gpointer))qof_instance_version_cmp,
768 };
769 
770 
771 gboolean gnc_lot_register (void)
772 {
773  static const QofParam params[] =
774  {
775  {
776  LOT_TITLE, QOF_TYPE_STRING,
778  (QofSetterFunc) gnc_lot_set_title
779  },
780  {
781  LOT_NOTES, QOF_TYPE_STRING,
782  (QofAccessFunc) gnc_lot_get_notes,
783  (QofSetterFunc) gnc_lot_set_notes
784  },
785  {
786  QOF_PARAM_GUID, QOF_TYPE_GUID,
788  },
789  {
790  QOF_PARAM_BOOK, QOF_ID_BOOK,
791  (QofAccessFunc) gnc_lot_get_book, NULL
792  },
793  {
794  LOT_IS_CLOSED, QOF_TYPE_BOOLEAN,
796  },
797  {
798  LOT_BALANCE, QOF_TYPE_NUMERIC,
800  },
801  { NULL },
802  };
803 
804  qof_class_register (GNC_ID_LOT, NULL, params);
805  return qof_object_register(&gncLotDesc);
806 }
807 
809 {
810  GNCLot * lot;
811  gint64 id = 0;
812  gchar *buff;
813 
814  lot = gnc_lot_new (qof_instance_get_book(acc));
815 
816  /* Provide a reasonable title for the new lot */
817  xaccAccountBeginEdit (acc);
818  qof_instance_get (QOF_INSTANCE (acc), "lot-next-id", &id, NULL);
819  buff = g_strdup_printf ("%s %" G_GINT64_FORMAT, _("Lot"), id);
820  gnc_lot_set_title (lot, buff);
821  id ++;
822  qof_instance_set (QOF_INSTANCE (acc), "lot-next-id", id, NULL);
823  xaccAccountCommitEdit (acc);
824  g_free (buff);
825  return lot;
826 }
827 
828 /* ========================== END OF FILE ========================= */
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.
gchar * gnc_num_dbg_to_string(gnc_numeric n)
Convert to string.
void qof_instance_get(const QofInstance *inst, const gchar *first_prop,...)
Wrapper for g_object_get.
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:257
QofInstance * qof_collection_lookup_entity(const QofCollection *col, const GncGUID *guid)
Find the entity going only from its guid.
Definition: qofid.cpp:215
GncInvoice * gnc_lot_get_cached_invoice(const GNCLot *lot)
The gnc_lot_get_cached_invoice() routine returns the invoice with which this lot is associated...
Definition: gnc-lot.c:400
QofBackendError
The errors that can be reported to the GUI & other front-end users.
Definition: qofbackend.h:57
Identifies that something sold at one time was bought at another.
Definition: gnc-lot.c:60
gboolean qof_instance_get_destroying(gconstpointer ptr)
Retrieve the flag that indicates whether or not this object is about to be destroyed.
void qof_instance_set(QofInstance *inst, const gchar *first_prop,...)
Wrapper for g_object_set Group setting multiple parameters in a single begin/commit/rollback.
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
void gnc_lot_add_split(GNCLot *lot, Split *split)
The gnc_lot_add_split() routine adds a split to this lot.
Definition: gnc-lot.c:622
Split * xaccSplitGetGainsSourceSplit(const Split *split)
The xaccSplitGetGainsSourceSplit() routine returns the split that is the source of the cap gains in t...
Definition: cap-gains.c:505
void xaccAccountInsertLot(Account *acc, GNCLot *lot)
The xaccAccountInsertLot() method will register the indicated lot with this account.
Definition: Account.cpp:2124
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
#define QOF_OBJECT_VERSION
Defines the version of the core object object registration interface.
Definition: qofobject.h:64
gboolean qof_commit_edit(QofInstance *inst)
commit_edit helpers
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
#define QOF_PARAM_BOOK
"Known" Object Parameters – all objects must support these
Definition: qofquery.h:109
void gnc_lot_set_closed_unknown(GNCLot *lot)
Reset closed flag so that it will be recalculated.
Definition: gnc-lot.c:425
void qof_collection_foreach(const QofCollection *col, QofInstanceForeachCB cb_func, gpointer user_data)
Call the callback for each entity in the collection.
Definition: qofid.cpp:323
void(* QofSetterFunc)(gpointer, gpointer)
The QofSetterFunc defines an function pointer for parameter setters.
Definition: qofclass.h:184
void qof_instance_get_kvp(QofInstance *, GValue *value, unsigned count,...)
Retrieves the contents of a KVP slot into a provided GValue.
Split * gnc_lot_get_earliest_split(GNCLot *lot)
The gnc_lot_get_earliest_split() routine is a convenience routine that helps identify the earliest da...
Definition: gnc-lot.c:701
const char * gnc_lot_get_title(const GNCLot *lot)
Get and set the account title, or the account notes, or the marker.
Definition: gnc-lot.c:456
Split * gnc_lot_get_latest_split(GNCLot *lot)
The gnc_lot_get_latest_split() routine is a convenience routine that helps identify the date this lot...
Definition: gnc-lot.c:713
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
GList SplitList
GList of Split.
Definition: gnc-engine.h:211
Account handling public routines.
SplitList * gnc_lot_get_split_list(const GNCLot *lot)
The gnc_lot_get_split_list() routine returns a GList of all the splits in this lot.
Definition: gnc-lot.c:436
void gnc_lot_get_balance_before(const GNCLot *lot, const Split *split, gnc_numeric *amount, gnc_numeric *value)
The gnc_lot_get_balance_before routine computes both the balance and value in the lot considering onl...
Definition: gnc-lot.c:572
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:177
void qof_collection_mark_clean(QofCollection *)
reset value of dirty flag
Definition: qofid.cpp:263
#define GNC_INVOICE_ID
STRING CONSTANTS ********************************************** Used to declare constant KVP keys use...
Definition: gnc-engine.h:261
const GncGUID * qof_entity_get_guid(gconstpointer ent)
void xaccSplitSetLot(Split *split, GNCLot *lot)
Assigns the split to a specific Lot.
Definition: Split.c:1887
Business Invoice Interface.
GNCLot * gnc_lot_make_default(Account *acc)
XXX: Document?
Definition: gnc-lot.c:808
gboolean gnc_lot_is_closed(GNCLot *lot)
The gnc_lot_is_closed() routine returns a boolean flag: is this lot closed? A lot is closed if its ba...
Definition: gnc-lot.c:382
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction&#39;s commodity.
Definition: gmock-Split.cpp:84
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1430
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
Definition: gmock-Split.cpp:53
This is the private header for the account structure.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
int xaccTransOrder(const Transaction *ta, const Transaction *tb)
The xaccTransOrder(ta,tb) method is useful for sorting.
Definition: Transaction.c:1894
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
Definition: qofbook.cpp:604
Account * gnc_lot_get_account(const GNCLot *lot)
The gnc_lot_get_account() routine returns the account with which this lot is associated.
Definition: gnc-lot.c:392
gboolean qof_object_register(const QofObject *object)
Register new types of object objects.
Definition: qofobject.cpp:317
const char * xaccAccountGetName(const Account *acc)
Get the account&#39;s name.
Definition: Account.cpp:3258
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
No error.
Definition: gnc-numeric.h:224
API for Transactions and Splits (journal entries)
The type used to store guids in C.
Definition: guid.h:75
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1471
Utilities to Automatically Compute Capital Gains/Losses.
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
The gnc_lot_get_balance() routine returns the balance of the lot.
Definition: gnc-lot.c:530
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account&#39;s commodity.
Definition: gmock-Split.cpp:69