GnuCash  5.6-150-g038405b370+
gnc-lot.cpp
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.hpp"
50 #include "gnc-lot.h"
51 #include "gnc-lot-p.h"
52 #include "cap-gains.h"
53 #include "Transaction.h"
54 #include "TransactionP.hpp"
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*)gnc_lot_get_instance_private((GNCLot*)o))
104 
105 #define gnc_lot_set_guid(L,G) qof_instance_set_guid(QOF_INSTANCE(L),&(G))
106 
107 /* ============================================================= */
108 
109 /* GObject Initialization */
110 G_DEFINE_TYPE_WITH_PRIVATE(GNCLot, gnc_lot, QOF_TYPE_INSTANCE)
111 
112 static void
113 gnc_lot_init(GNCLot* lot)
114 {
115  GNCLotPrivate* priv;
116 
117  priv = GET_PRIVATE(lot);
118  priv->account = nullptr;
119  priv->splits = nullptr;
120  priv->cached_invoice = nullptr;
121  priv->is_closed = LOT_CLOSED_UNKNOWN;
122  priv->marker = 0;
123 }
124 
125 static void
126 gnc_lot_dispose(GObject *lotp)
127 {
128  G_OBJECT_CLASS(gnc_lot_parent_class)->dispose(lotp);
129 }
130 
131 static void
132 gnc_lot_finalize(GObject* lotp)
133 {
134  G_OBJECT_CLASS(gnc_lot_parent_class)->finalize(lotp);
135 }
136 
137 static void
138 gnc_lot_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
139 {
140  GNCLot* lot;
141  GNCLotPrivate* priv;
142 
143  g_return_if_fail(GNC_IS_LOT(object));
144 
145  lot = GNC_LOT(object);
146  priv = GET_PRIVATE(lot);
147  switch (prop_id)
148  {
149  case PROP_IS_CLOSED:
150  g_value_set_int(value, priv->is_closed);
151  break;
152  case PROP_MARKER:
153  g_value_set_int(value, priv->marker);
154  break;
155  case PROP_INVOICE:
156  qof_instance_get_kvp (QOF_INSTANCE (lot), value, 2, GNC_INVOICE_ID, GNC_INVOICE_GUID);
157  break;
158  case PROP_OWNER_TYPE:
159  qof_instance_get_kvp (QOF_INSTANCE (lot), value, 2, GNC_OWNER_ID, GNC_OWNER_TYPE);
160  break;
161  case PROP_OWNER_GUID:
162  qof_instance_get_kvp (QOF_INSTANCE (lot), value, 2, GNC_OWNER_ID, GNC_OWNER_GUID);
163  break;
164  default:
165  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
166  break;
167  }
168 }
169 
170 static void
171 gnc_lot_set_property (GObject* object,
172  guint prop_id,
173  const GValue* value,
174  GParamSpec* pspec)
175 {
176  GNCLot* lot;
177  GNCLotPrivate* priv;
178 
179  g_return_if_fail(GNC_IS_LOT(object));
180 
181  lot = GNC_LOT(object);
182  if (prop_id < PROP_RUNTIME_0)
183  g_assert (qof_instance_get_editlevel(lot));
184 
185  priv = GET_PRIVATE(lot);
186  switch (prop_id)
187  {
188  case PROP_IS_CLOSED:
189  priv->is_closed = g_value_get_int(value);
190  break;
191  case PROP_MARKER:
192  priv->marker = g_value_get_int(value);
193  break;
194  case PROP_INVOICE:
195  qof_instance_set_kvp (QOF_INSTANCE (lot), value, 2, GNC_INVOICE_ID, GNC_INVOICE_GUID);
196  break;
197  case PROP_OWNER_TYPE:
198  qof_instance_set_kvp (QOF_INSTANCE (lot), value, 2, GNC_OWNER_ID, GNC_OWNER_TYPE);
199  break;
200  case PROP_OWNER_GUID:
201  qof_instance_set_kvp (QOF_INSTANCE (lot), value, 2, GNC_OWNER_ID, GNC_OWNER_GUID);
202  break;
203  default:
204  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
205  break;
206  }
207 }
208 
209 static void
210 gnc_lot_class_init(GNCLotClass* klass)
211 {
212  GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
213 
214  gobject_class->dispose = gnc_lot_dispose;
215  gobject_class->finalize = gnc_lot_finalize;
216  gobject_class->get_property = gnc_lot_get_property;
217  gobject_class->set_property = gnc_lot_set_property;
218 
219  g_object_class_install_property(
220  gobject_class,
221  PROP_IS_CLOSED,
222  g_param_spec_int("is-closed",
223  "Is Lot Closed",
224  "Indication of whether this lot is open "
225  "or closed to further changes.",
226  -1, 1, 0,
227  G_PARAM_READWRITE));
228 
229  g_object_class_install_property(
230  gobject_class,
231  PROP_MARKER,
232  g_param_spec_int("marker",
233  "Lot marker",
234  "Ipsum Lorem",
235  0, G_MAXINT8, 0,
236  G_PARAM_READWRITE));
237 
238  g_object_class_install_property(
239  gobject_class,
240  PROP_INVOICE,
241  g_param_spec_boxed("invoice",
242  "Invoice attached to lot",
243  "Used by GncInvoice",
244  GNC_TYPE_GUID,
245  G_PARAM_READWRITE));
246 
247  g_object_class_install_property(
248  gobject_class,
249  PROP_OWNER_TYPE,
250  g_param_spec_int64("owner-type",
251  "Owning Entity Type of lot",
252  "Used by GncOwner",
253  0, G_MAXINT64, 0,
254  G_PARAM_READWRITE));
255 
256  g_object_class_install_property(
257  gobject_class,
258  PROP_OWNER_GUID,
259  g_param_spec_boxed("owner-guid",
260  "Owner attached to lot",
261  "Used by GncOwner",
262  GNC_TYPE_GUID,
263  G_PARAM_READWRITE));
264 }
265 
266 GNCLot *
267 gnc_lot_new (QofBook *book)
268 {
269  GNCLot *lot;
270  g_return_val_if_fail (book, nullptr);
271 
272  lot = GNC_LOT(g_object_new (GNC_TYPE_LOT, nullptr));
273  qof_instance_init_data(QOF_INSTANCE(lot), GNC_ID_LOT, book);
274  qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_CREATE, nullptr);
275  return lot;
276 }
277 
278 static void
279 gnc_lot_free(GNCLot* lot)
280 {
281  GList *node;
282  GNCLotPrivate* priv;
283  if (!lot) return;
284 
285  ENTER ("(lot=%p)", lot);
286  qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_DESTROY, nullptr);
287 
288  priv = GET_PRIVATE(lot);
289  for (node = priv->splits; node; node = node->next)
290  {
291  Split *s = GNC_SPLIT(node->data);
292  s->lot = nullptr;
293  }
294  g_list_free (priv->splits);
295 
296  if (priv->account && !qof_instance_get_destroying(priv->account))
297  xaccAccountRemoveLot (priv->account, lot);
298 
299  priv->account = nullptr;
300  priv->is_closed = TRUE;
301  /* qof_instance_release (&lot->inst); */
302  g_object_unref (lot);
303 
304  LEAVE();
305 }
306 
307 void
308 gnc_lot_destroy (GNCLot *lot)
309 {
310  if (!lot) return;
311 
312  gnc_lot_begin_edit(lot);
313  qof_instance_set_destroying(lot, TRUE);
314  gnc_lot_commit_edit(lot);
315 }
316 
317 /* ============================================================= */
318 
319 void
320 gnc_lot_begin_edit (GNCLot *lot)
321 {
322  qof_begin_edit(QOF_INSTANCE(lot));
323 }
324 
325 static void commit_err (QofInstance *inst, QofBackendError errcode)
326 {
327  PERR ("Failed to commit: %d", errcode);
328  gnc_engine_signal_commit_error( errcode );
329 }
330 
331 static void lot_free(QofInstance* inst)
332 {
333  GNCLot* lot = GNC_LOT(inst);
334 
335  gnc_lot_free(lot);
336 }
337 
338 static void noop (QofInstance *inst) {}
339 
340 void
341 gnc_lot_commit_edit (GNCLot *lot)
342 {
343  if (!qof_commit_edit (QOF_INSTANCE(lot))) return;
344  qof_commit_edit_part2 (QOF_INSTANCE(lot), commit_err, noop, lot_free);
345 }
346 
347 /* ============================================================= */
348 
349 GNCLot *
350 gnc_lot_lookup (const GncGUID *guid, QofBook *book)
351 {
352  QofCollection *col;
353  if (!guid || !book) return nullptr;
354  col = qof_book_get_collection (book, GNC_ID_LOT);
355  return (GNCLot *) qof_collection_lookup_entity (col, guid);
356 }
357 
358 QofBook *
359 gnc_lot_get_book (GNCLot *lot)
360 {
361  return qof_instance_get_book(QOF_INSTANCE(lot));
362 }
363 
364 /* ============================================================= */
365 
366 gboolean
367 gnc_lot_is_closed (GNCLot *lot)
368 {
369  GNCLotPrivate* priv;
370  if (!lot) return TRUE;
371  priv = GET_PRIVATE(lot);
372  if (0 > priv->is_closed) gnc_lot_get_balance (lot);
373  return priv->is_closed;
374 }
375 
376 Account *
377 gnc_lot_get_account (const GNCLot *lot)
378 {
379  GNCLotPrivate* priv;
380  if (!lot) return nullptr;
381  priv = GET_PRIVATE(lot);
382  return priv->account;
383 }
384 
385 GncInvoice * gnc_lot_get_cached_invoice (const GNCLot *lot)
386 {
387  if (!lot) return nullptr;
388  else
389  {
390  GNCLotPrivate *priv = GET_PRIVATE(lot);
391  return priv->cached_invoice;
392  }
393 }
394 
395 void
396 gnc_lot_set_cached_invoice(GNCLot* lot, GncInvoice *invoice)
397 {
398  if (!lot) return;
399  GET_PRIVATE(lot)->cached_invoice = invoice;
400 }
401 
402 void
403 gnc_lot_set_account(GNCLot* lot, Account* account)
404 {
405  if (lot != nullptr)
406  {
407  GNCLotPrivate* priv;
408  priv = GET_PRIVATE(lot);
409  priv->account = account;
410  }
411 }
412 
413 void
415 {
416  GNCLotPrivate* priv;
417  if (lot != nullptr)
418  {
419  priv = GET_PRIVATE(lot);
420  priv->is_closed = LOT_CLOSED_UNKNOWN;
421  }
422 }
423 
424 SplitList *
425 gnc_lot_get_split_list (const GNCLot *lot)
426 {
427  GNCLotPrivate* priv;
428  if (!lot) return nullptr;
429  priv = GET_PRIVATE(lot);
430  return priv->splits;
431 }
432 
433 gint gnc_lot_count_splits (const GNCLot *lot)
434 {
435  GNCLotPrivate* priv;
436  if (!lot) return 0;
437  priv = GET_PRIVATE(lot);
438  return g_list_length (priv->splits);
439 }
440 
441 /* ============================================================== */
442 /* Hmm, we should probably inline these. */
443 
444 const char *
445 gnc_lot_get_title (const GNCLot *lot)
446 {
447  if (!lot) return nullptr;
448 
449  GValue v = G_VALUE_INIT;
450  qof_instance_get_kvp (QOF_INSTANCE (lot), &v, 1, "title");
451  const char *rv = G_VALUE_HOLDS_STRING (&v) ? g_value_get_string (&v) : nullptr;
452  g_value_unset (&v);
453 
454  return rv;
455 }
456 
457 const char *
458 gnc_lot_get_notes (const GNCLot *lot)
459 {
460  if (!lot) return nullptr;
461 
462  GValue v = G_VALUE_INIT;
463  qof_instance_get_kvp (QOF_INSTANCE (lot), &v, 1, "notes");
464  const char *rv = G_VALUE_HOLDS_STRING (&v) ? g_value_get_string (&v) : nullptr;
465  g_value_unset (&v);
466  return rv;
467 }
468 
469 void
470 gnc_lot_set_title (GNCLot *lot, const char *str)
471 {
472  GValue v = G_VALUE_INIT;
473  if (!lot) return;
474 
475  qof_begin_edit(QOF_INSTANCE(lot));
476  g_value_init (&v, G_TYPE_STRING);
477  g_value_set_static_string (&v, str);
478  qof_instance_set_kvp (QOF_INSTANCE (lot), &v, 1, "title");
479  qof_instance_set_dirty(QOF_INSTANCE(lot));
480  gnc_lot_commit_edit(lot);
481  g_value_unset (&v);
482 }
483 
484 void
485 gnc_lot_set_notes (GNCLot *lot, const char *str)
486 {
487  GValue v = G_VALUE_INIT;
488  if (!lot) return;
489 
490  qof_begin_edit(QOF_INSTANCE(lot));
491  g_value_init (&v, G_TYPE_STRING);
492  g_value_set_static_string (&v, str);
493  qof_instance_set_kvp (QOF_INSTANCE (lot), &v, 1, "notes");
494  qof_instance_set_dirty(QOF_INSTANCE(lot));
495  gnc_lot_commit_edit(lot);
496  g_value_unset (&v);
497 }
498 
499 /* ============================================================= */
500 
501 gnc_numeric
502 gnc_lot_get_balance (GNCLot *lot)
503 {
504  GNCLotPrivate* priv;
505  GList *node;
506  gnc_numeric zero = gnc_numeric_zero();
507  gnc_numeric baln = zero;
508  if (!lot) return zero;
509 
510  priv = GET_PRIVATE(lot);
511  if (!priv->splits)
512  {
513  priv->is_closed = FALSE;
514  return zero;
515  }
516 
517  /* Sum over splits; because they all belong to same account
518  * they will have same denominator.
519  */
520  for (node = priv->splits; node; node = node->next)
521  {
522  Split *s = GNC_SPLIT(node->data);
523  gnc_numeric amt = xaccSplitGetAmount (s);
524  baln = gnc_numeric_add_fixed (baln, amt);
525  g_assert (gnc_numeric_check (baln) == GNC_ERROR_OK);
526  }
527 
528  /* cache a zero balance as a closed lot */
529  if (gnc_numeric_equal (baln, zero))
530  {
531  priv->is_closed = TRUE;
532  }
533  else
534  {
535  priv->is_closed = FALSE;
536  }
537 
538  return baln;
539 }
540 
541 /* ============================================================= */
542 
543 void
544 gnc_lot_get_balance_before (const GNCLot *lot, const Split *split,
545  gnc_numeric *amount, gnc_numeric *value)
546 {
547  GNCLotPrivate* priv;
548  GList *node;
549  gnc_numeric zero = gnc_numeric_zero();
550  gnc_numeric amt = zero;
551  gnc_numeric val = zero;
552 
553  *amount = amt;
554  *value = val;
555  if (lot == nullptr) return;
556 
557  priv = GET_PRIVATE(lot);
558  if (priv->splits)
559  {
560  Transaction *ta, *tb;
561  const Split *target;
562  /* If this is a gains split, find the source of the gains and use
563  its transaction for the comparison. Gains splits are in separate
564  transactions that may sort after non-gains transactions. */
565  target = xaccSplitGetGainsSourceSplit (split);
566  if (target == nullptr)
567  target = split;
568  tb = xaccSplitGetParent (target);
569  for (node = priv->splits; node; node = node->next)
570  {
571  Split *s = GNC_SPLIT(node->data);
572  Split *source = xaccSplitGetGainsSourceSplit (s);
573  if (source == nullptr)
574  source = s;
575  ta = xaccSplitGetParent (source);
576  if ((ta == tb && source != target) ||
577  xaccTransOrder (ta, tb) < 0)
578  {
579  gnc_numeric tmpval = xaccSplitGetAmount (s);
580  amt = gnc_numeric_add_fixed (amt, tmpval);
581  tmpval = xaccSplitGetValue (s);
582  val = gnc_numeric_add_fixed (val, tmpval);
583  }
584  }
585  }
586 
587  *amount = amt;
588  *value = val;
589 }
590 
591 /* ============================================================= */
592 
593 void
594 gnc_lot_add_split (GNCLot *lot, Split *split)
595 {
596  GNCLotPrivate* priv;
597  Account * acc;
598  if (!lot || !split) return;
599  priv = GET_PRIVATE(lot);
600 
601  ENTER ("(lot=%p, split=%p) %s amt=%s val=%s", lot, split,
602  gnc_lot_get_title (lot),
603  gnc_num_dbg_to_string (split->amount),
604  gnc_num_dbg_to_string (split->value));
605  gnc_lot_begin_edit(lot);
606  acc = xaccSplitGetAccount (split);
607  qof_instance_set_dirty(QOF_INSTANCE(lot));
608  if (nullptr == priv->account)
609  {
610  xaccAccountInsertLot (acc, lot);
611  }
612  else if (priv->account != acc)
613  {
614  PERR ("splits from different accounts cannot "
615  "be added to this lot!\n"
616  "\tlot account=\'%s\', split account=\'%s\'\n",
617  xaccAccountGetName(priv->account), xaccAccountGetName (acc));
618  gnc_lot_commit_edit(lot);
619  LEAVE("different accounts");
620  return;
621  }
622 
623  if (lot == split->lot)
624  {
625  gnc_lot_commit_edit(lot);
626  LEAVE("already in lot");
627  return; /* handle not-uncommon no-op */
628  }
629  if (split->lot)
630  {
631  gnc_lot_remove_split (split->lot, split);
632  }
633  xaccSplitSetLot(split, lot);
634 
635  priv->splits = g_list_append (priv->splits, split);
636 
637  /* for recomputation of is-closed */
638  priv->is_closed = LOT_CLOSED_UNKNOWN;
639  gnc_lot_commit_edit(lot);
640 
641  qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_MODIFY, nullptr);
642  LEAVE("added to lot");
643 }
644 
645 void
646 gnc_lot_remove_split (GNCLot *lot, Split *split)
647 {
648  GNCLotPrivate* priv;
649  if (!lot || !split) return;
650  priv = GET_PRIVATE(lot);
651 
652  ENTER ("(lot=%p, split=%p)", lot, split);
653  gnc_lot_begin_edit(lot);
654  qof_instance_set_dirty(QOF_INSTANCE(lot));
655  priv->splits = g_list_remove (priv->splits, split);
656  xaccSplitSetLot(split, nullptr);
657  priv->is_closed = LOT_CLOSED_UNKNOWN; /* force an is-closed computation */
658 
659  if (!priv->splits && priv->account)
660  {
661  xaccAccountRemoveLot (priv->account, lot);
662  priv->account = nullptr;
663  }
664  gnc_lot_commit_edit(lot);
665  qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_MODIFY, nullptr);
666  LEAVE("removed from lot");
667 }
668 
669 /* ============================================================== */
670 /* Utility function, get earliest split in lot */
671 
672 Split *
674 {
675  GNCLotPrivate* priv;
676  if (!lot) return nullptr;
677  priv = GET_PRIVATE(lot);
678  if (! priv->splits) return nullptr;
679  priv->splits = g_list_sort (priv->splits, (GCompareFunc) xaccSplitOrderDateOnly);
680  return GNC_SPLIT(priv->splits->data);
681 }
682 
683 /* Utility function, get latest split in lot */
684 Split *
686 {
687  GNCLotPrivate* priv;
688  SplitList *node;
689 
690  if (!lot) return nullptr;
691  priv = GET_PRIVATE(lot);
692  if (! priv->splits) return nullptr;
693  priv->splits = g_list_sort (priv->splits, (GCompareFunc) xaccSplitOrderDateOnly);
694 
695  for (node = priv->splits; node->next; node = node->next)
696  ;
697 
698  return GNC_SPLIT(node->data);
699 }
700 
701 /* ============================================================= */
702 
703 static void
704 destroy_lot_on_book_close(QofInstance *ent, gpointer data)
705 {
706  GNCLot* lot = GNC_LOT(ent);
707 
708  gnc_lot_destroy(lot);
709 }
710 
711 static void
712 gnc_lot_book_end(QofBook* book)
713 {
714  QofCollection *col;
715 
716  col = qof_book_get_collection(book, GNC_ID_LOT);
717  qof_collection_foreach(col, destroy_lot_on_book_close, nullptr);
718 }
719 
720 #ifdef _MSC_VER
721 /* MSVC compiler doesn't have C99 "designated initializers"
722  * so we wrap them in a macro that is empty on MSVC. */
723 # define DI(x) /* */
724 #else
725 # define DI(x) x
726 #endif
727 static QofObject gncLotDesc =
728 {
729  DI(.interface_version = ) QOF_OBJECT_VERSION,
730  DI(.e_type = ) GNC_ID_LOT,
731  DI(.type_label = ) "Lot",
732  DI(.create = ) (void* (*)(QofBook*))gnc_lot_new,
733  DI(.book_begin = ) nullptr,
734  DI(.book_end = ) gnc_lot_book_end,
735  DI(.is_dirty = ) qof_collection_is_dirty,
736  DI(.mark_clean = ) qof_collection_mark_clean,
737  DI(.foreach = ) qof_collection_foreach,
738  DI(.printable = ) nullptr,
739  DI(.version_cmp = ) (int (*)(gpointer, gpointer))qof_instance_version_cmp,
740 };
741 
742 
743 gboolean gnc_lot_register (void)
744 {
745  static const QofParam params[] =
746  {
747  {
748  LOT_TITLE, QOF_TYPE_STRING,
749  (QofAccessFunc) gnc_lot_get_title,
750  (QofSetterFunc) gnc_lot_set_title
751  },
752  {
753  LOT_NOTES, QOF_TYPE_STRING,
754  (QofAccessFunc) gnc_lot_get_notes,
755  (QofSetterFunc) gnc_lot_set_notes
756  },
757  {
758  QOF_PARAM_GUID, QOF_TYPE_GUID,
760  },
761  {
762  QOF_PARAM_BOOK, QOF_ID_BOOK,
763  (QofAccessFunc) gnc_lot_get_book, nullptr
764  },
765  {
766  LOT_IS_CLOSED, QOF_TYPE_BOOLEAN,
768  },
769  {
770  LOT_BALANCE, QOF_TYPE_NUMERIC,
772  },
773  { nullptr },
774  };
775 
776  qof_class_register (GNC_ID_LOT, nullptr, params);
777  return qof_object_register(&gncLotDesc);
778 }
779 
781 {
782  GNCLot * lot;
783  gint64 id = 0;
784  gchar *buff;
785 
786  lot = gnc_lot_new (qof_instance_get_book(acc));
787 
788  /* Provide a reasonable title for the new lot */
789  xaccAccountBeginEdit (acc);
790  qof_instance_get (QOF_INSTANCE (acc), "lot-next-id", &id, nullptr);
791  buff = g_strdup_printf ("%s %" G_GINT64_FORMAT, _("Lot"), id);
792  gnc_lot_set_title (lot, buff);
793  id ++;
794  qof_instance_set (QOF_INSTANCE (acc), "lot-next-id", id, nullptr);
795  xaccAccountCommitEdit (acc);
796  g_free (buff);
797  return lot;
798 }
799 
800 /* ========================== END OF FILE ========================= */
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
Compare two instances, based on their last update times.
This is the private header for the account structure.
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:255
QofInstance * qof_collection_lookup_entity(const QofCollection *col, const GncGUID *guid)
Find the entity going only from its guid.
Definition: qofid.cpp:212
GncInvoice * gnc_lot_get_cached_invoice(const GNCLot *lot)
Returns the invoice with which this lot is associated.
Definition: gnc-lot.cpp:385
QofBackendError
The errors that can be reported to the GUI & other front-end users.
Definition: qofbackend.h:57
STRUCTS.
Identifies that something sold at one time was bought at another.
Definition: gnc-lot.cpp: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)
Adds a split to this lot.
Definition: gnc-lot.cpp:594
Split * xaccSplitGetGainsSourceSplit(const Split *split)
The xaccSplitGetGainsSourceSplit() routine returns the split that is the source of the cap gains in t...
Definition: cap-gains.cpp:503
void xaccAccountInsertLot(Account *acc, GNCLot *lot)
The xaccAccountInsertLot() method will register the indicated lot with this account.
Definition: Account.cpp:2122
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:63
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:108
void gnc_lot_set_closed_unknown(GNCLot *lot)
Reset closed flag so that it will be recalculated.
Definition: gnc-lot.cpp:414
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.
Split * gnc_lot_get_earliest_split(GNCLot *lot)
Convenience routine to identify the earliest date in the lot.
Definition: gnc-lot.cpp:673
Split * gnc_lot_get_latest_split(GNCLot *lot)
Convenience routineto identify the date this lot was closed.
Definition: gnc-lot.cpp:685
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:207
Account handling public routines.
SplitList * gnc_lot_get_split_list(const GNCLot *lot)
Returns a list of all the splits in this lot.
Definition: gnc-lot.cpp:425
void gnc_lot_remove_split(GNCLot *lot, Split *split)
Adds a split from this lot.
Definition: gnc-lot.cpp:646
void gnc_lot_get_balance_before(const GNCLot *lot, const Split *split, gnc_numeric *amount, gnc_numeric *value)
Computes both the balance and value in the lot considering only splits in transactions prior to the o...
Definition: gnc-lot.cpp:544
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
#define GNC_INVOICE_ID
STRING CONSTANTS ********************************************** Used to declare constant KVP keys use...
Definition: gnc-engine.h:257
const GncGUID * qof_entity_get_guid(gconstpointer ent)
void xaccSplitSetLot(Split *split, GNCLot *lot)
Assigns the split to a specific Lot.
Definition: Split.cpp:1888
Business Invoice Interface.
GNCLot * gnc_lot_make_default(Account *acc)
Definition: gnc-lot.cpp:780
gboolean gnc_lot_is_closed(GNCLot *lot)
Returns closed status of the given lot.
Definition: gnc-lot.cpp:367
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:1475
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
Definition: gmock-Split.cpp:53
#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.
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:521
Account * gnc_lot_get_account(const GNCLot *lot)
Returns the account with which this lot is associated.
Definition: gnc-lot.cpp:377
gboolean qof_object_register(const QofObject *object)
Register new types of object objects.
Definition: qofobject.cpp:299
const char * xaccAccountGetName(const Account *acc)
Get the account&#39;s name.
Definition: Account.cpp:3239
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:223
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:1516
Utilities to Automatically Compute Capital Gains/Losses.
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
Returns the lot balance.
Definition: gnc-lot.cpp:502
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account&#39;s commodity.
Definition: gmock-Split.cpp:69