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  auto str{qof_instance_get_path_kvp<const char*> (QOF_INSTANCE (lot), {"title"})};
450  return str ? *str : nullptr;
451 }
452 
453 const char *
454 gnc_lot_get_notes (const GNCLot *lot)
455 {
456  if (!lot) return nullptr;
457 
458  auto str{qof_instance_get_path_kvp<const char*> (QOF_INSTANCE (lot), {"notes"})};
459  return str ? *str : nullptr;
460 }
461 
462 void
463 gnc_lot_set_title (GNCLot *lot, const char *str)
464 {
465  if (!lot) return;
466 
467  qof_begin_edit(QOF_INSTANCE(lot));
468  qof_instance_set_path_kvp<const char*> (QOF_INSTANCE (lot), g_strdup(str), {"title"});
469  qof_instance_set_dirty(QOF_INSTANCE(lot));
470  gnc_lot_commit_edit(lot);
471 }
472 
473 void
474 gnc_lot_set_notes (GNCLot *lot, const char *str)
475 {
476  if (!lot) return;
477 
478  qof_begin_edit(QOF_INSTANCE(lot));
479  qof_instance_set_path_kvp<const char*> (QOF_INSTANCE (lot), g_strdup(str), {"notes"});
480  qof_instance_set_dirty(QOF_INSTANCE(lot));
481  gnc_lot_commit_edit(lot);
482 }
483 
484 /* ============================================================= */
485 
486 gnc_numeric
487 gnc_lot_get_balance (GNCLot *lot)
488 {
489  GNCLotPrivate* priv;
490  GList *node;
491  gnc_numeric zero = gnc_numeric_zero();
492  gnc_numeric baln = zero;
493  if (!lot) return zero;
494 
495  priv = GET_PRIVATE(lot);
496  if (!priv->splits)
497  {
498  priv->is_closed = FALSE;
499  return zero;
500  }
501 
502  /* Sum over splits; because they all belong to same account
503  * they will have same denominator.
504  */
505  for (node = priv->splits; node; node = node->next)
506  {
507  Split *s = GNC_SPLIT(node->data);
508  gnc_numeric amt = xaccSplitGetAmount (s);
509  baln = gnc_numeric_add_fixed (baln, amt);
510  g_assert (gnc_numeric_check (baln) == GNC_ERROR_OK);
511  }
512 
513  /* cache a zero balance as a closed lot */
514  if (gnc_numeric_equal (baln, zero))
515  {
516  priv->is_closed = TRUE;
517  }
518  else
519  {
520  priv->is_closed = FALSE;
521  }
522 
523  return baln;
524 }
525 
526 /* ============================================================= */
527 
528 void
529 gnc_lot_get_balance_before (const GNCLot *lot, const Split *split,
530  gnc_numeric *amount, gnc_numeric *value)
531 {
532  GNCLotPrivate* priv;
533  GList *node;
534  gnc_numeric zero = gnc_numeric_zero();
535  gnc_numeric amt = zero;
536  gnc_numeric val = zero;
537 
538  *amount = amt;
539  *value = val;
540  if (lot == nullptr) return;
541 
542  priv = GET_PRIVATE(lot);
543  if (priv->splits)
544  {
545  Transaction *ta, *tb;
546  const Split *target;
547  /* If this is a gains split, find the source of the gains and use
548  its transaction for the comparison. Gains splits are in separate
549  transactions that may sort after non-gains transactions. */
550  target = xaccSplitGetGainsSourceSplit (split);
551  if (target == nullptr)
552  target = split;
553  tb = xaccSplitGetParent (target);
554  for (node = priv->splits; node; node = node->next)
555  {
556  Split *s = GNC_SPLIT(node->data);
557  Split *source = xaccSplitGetGainsSourceSplit (s);
558  if (source == nullptr)
559  source = s;
560  ta = xaccSplitGetParent (source);
561  if ((ta == tb && source != target) ||
562  xaccTransOrder (ta, tb) < 0)
563  {
564  gnc_numeric tmpval = xaccSplitGetAmount (s);
565  amt = gnc_numeric_add_fixed (amt, tmpval);
566  tmpval = xaccSplitGetValue (s);
567  val = gnc_numeric_add_fixed (val, tmpval);
568  }
569  }
570  }
571 
572  *amount = amt;
573  *value = val;
574 }
575 
576 /* ============================================================= */
577 
578 void
579 gnc_lot_add_split (GNCLot *lot, Split *split)
580 {
581  GNCLotPrivate* priv;
582  Account * acc;
583  if (!lot || !split) return;
584  priv = GET_PRIVATE(lot);
585 
586  ENTER ("(lot=%p, split=%p) %s amt=%s val=%s", lot, split,
587  gnc_lot_get_title (lot),
588  gnc_num_dbg_to_string (split->amount),
589  gnc_num_dbg_to_string (split->value));
590  gnc_lot_begin_edit(lot);
591  acc = xaccSplitGetAccount (split);
592  qof_instance_set_dirty(QOF_INSTANCE(lot));
593  if (nullptr == priv->account)
594  {
595  xaccAccountInsertLot (acc, lot);
596  }
597  else if (priv->account != acc)
598  {
599  PERR ("splits from different accounts cannot "
600  "be added to this lot!\n"
601  "\tlot account=\'%s\', split account=\'%s\'\n",
602  xaccAccountGetName(priv->account), xaccAccountGetName (acc));
603  gnc_lot_commit_edit(lot);
604  LEAVE("different accounts");
605  return;
606  }
607 
608  if (lot == split->lot)
609  {
610  gnc_lot_commit_edit(lot);
611  LEAVE("already in lot");
612  return; /* handle not-uncommon no-op */
613  }
614  if (split->lot)
615  {
616  gnc_lot_remove_split (split->lot, split);
617  }
618  xaccSplitSetLot(split, lot);
619 
620  priv->splits = g_list_append (priv->splits, split);
621 
622  /* for recomputation of is-closed */
623  priv->is_closed = LOT_CLOSED_UNKNOWN;
624  gnc_lot_commit_edit(lot);
625 
626  qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_MODIFY, nullptr);
627  LEAVE("added to lot");
628 }
629 
630 void
631 gnc_lot_remove_split (GNCLot *lot, Split *split)
632 {
633  GNCLotPrivate* priv;
634  if (!lot || !split) return;
635  priv = GET_PRIVATE(lot);
636 
637  ENTER ("(lot=%p, split=%p)", lot, split);
638  gnc_lot_begin_edit(lot);
639  qof_instance_set_dirty(QOF_INSTANCE(lot));
640  priv->splits = g_list_remove (priv->splits, split);
641  xaccSplitSetLot(split, nullptr);
642  priv->is_closed = LOT_CLOSED_UNKNOWN; /* force an is-closed computation */
643 
644  if (!priv->splits && priv->account)
645  {
646  xaccAccountRemoveLot (priv->account, lot);
647  priv->account = nullptr;
648  }
649  gnc_lot_commit_edit(lot);
650  qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_MODIFY, nullptr);
651  LEAVE("removed from lot");
652 }
653 
654 /* ============================================================== */
655 /* Utility function, get earliest split in lot */
656 
657 Split *
659 {
660  GNCLotPrivate* priv;
661  if (!lot) return nullptr;
662  priv = GET_PRIVATE(lot);
663  if (! priv->splits) return nullptr;
664  priv->splits = g_list_sort (priv->splits, (GCompareFunc) xaccSplitOrderDateOnly);
665  return GNC_SPLIT(priv->splits->data);
666 }
667 
668 /* Utility function, get latest split in lot */
669 Split *
671 {
672  GNCLotPrivate* priv;
673  SplitList *node;
674 
675  if (!lot) return nullptr;
676  priv = GET_PRIVATE(lot);
677  if (! priv->splits) return nullptr;
678  priv->splits = g_list_sort (priv->splits, (GCompareFunc) xaccSplitOrderDateOnly);
679 
680  for (node = priv->splits; node->next; node = node->next)
681  ;
682 
683  return GNC_SPLIT(node->data);
684 }
685 
686 /* ============================================================= */
687 
688 static void
689 destroy_lot_on_book_close(QofInstance *ent, gpointer data)
690 {
691  GNCLot* lot = GNC_LOT(ent);
692 
693  gnc_lot_destroy(lot);
694 }
695 
696 static void
697 gnc_lot_book_end(QofBook* book)
698 {
699  QofCollection *col;
700 
701  col = qof_book_get_collection(book, GNC_ID_LOT);
702  qof_collection_foreach(col, destroy_lot_on_book_close, nullptr);
703 }
704 
705 #ifdef _MSC_VER
706 /* MSVC compiler doesn't have C99 "designated initializers"
707  * so we wrap them in a macro that is empty on MSVC. */
708 # define DI(x) /* */
709 #else
710 # define DI(x) x
711 #endif
712 static QofObject gncLotDesc =
713 {
714  DI(.interface_version = ) QOF_OBJECT_VERSION,
715  DI(.e_type = ) GNC_ID_LOT,
716  DI(.type_label = ) "Lot",
717  DI(.create = ) (void* (*)(QofBook*))gnc_lot_new,
718  DI(.book_begin = ) nullptr,
719  DI(.book_end = ) gnc_lot_book_end,
720  DI(.is_dirty = ) qof_collection_is_dirty,
721  DI(.mark_clean = ) qof_collection_mark_clean,
722  DI(.foreach = ) qof_collection_foreach,
723  DI(.printable = ) nullptr,
724  DI(.version_cmp = ) (int (*)(gpointer, gpointer))qof_instance_version_cmp,
725 };
726 
727 
728 gboolean gnc_lot_register (void)
729 {
730  static const QofParam params[] =
731  {
732  {
733  LOT_TITLE, QOF_TYPE_STRING,
734  (QofAccessFunc) gnc_lot_get_title,
735  (QofSetterFunc) gnc_lot_set_title
736  },
737  {
738  LOT_NOTES, QOF_TYPE_STRING,
739  (QofAccessFunc) gnc_lot_get_notes,
740  (QofSetterFunc) gnc_lot_set_notes
741  },
742  {
743  QOF_PARAM_GUID, QOF_TYPE_GUID,
745  },
746  {
747  QOF_PARAM_BOOK, QOF_ID_BOOK,
748  (QofAccessFunc) gnc_lot_get_book, nullptr
749  },
750  {
751  LOT_IS_CLOSED, QOF_TYPE_BOOLEAN,
753  },
754  {
755  LOT_BALANCE, QOF_TYPE_NUMERIC,
757  },
758  { nullptr },
759  };
760 
761  qof_class_register (GNC_ID_LOT, nullptr, params);
762  return qof_object_register(&gncLotDesc);
763 }
764 
766 {
767  GNCLot * lot;
768  gint64 id = 0;
769  gchar *buff;
770 
771  lot = gnc_lot_new (qof_instance_get_book(acc));
772 
773  /* Provide a reasonable title for the new lot */
774  xaccAccountBeginEdit (acc);
775  qof_instance_get (QOF_INSTANCE (acc), "lot-next-id", &id, nullptr);
776  buff = g_strdup_printf ("%s %" G_GINT64_FORMAT, _("Lot"), id);
777  gnc_lot_set_title (lot, buff);
778  id ++;
779  qof_instance_set (QOF_INSTANCE (acc), "lot-next-id", id, nullptr);
780  xaccAccountCommitEdit (acc);
781  g_free (buff);
782  return lot;
783 }
784 
785 /* ========================== 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:579
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:2142
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:658
Split * gnc_lot_get_latest_split(GNCLot *lot)
Convenience routineto identify the date this lot was closed.
Definition: gnc-lot.cpp:670
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:631
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:529
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:1890
Business Invoice Interface.
GNCLot * gnc_lot_make_default(Account *acc)
Definition: gnc-lot.cpp:765
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:1477
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 a)
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:3259
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:1518
Utilities to Automatically Compute Capital Gains/Losses.
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
Returns the lot balance.
Definition: gnc-lot.cpp:487
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account&#39;s commodity.
Definition: gmock-Split.cpp:69