GnuCash  5.6-150-g038405b370+
Split.cpp
1 /********************************************************************\
2  * Split.c -- split implementation *
3  * Copyright (C) 1997 Robin D. Clark *
4  * Copyright (C) 1997-2003 Linas Vepstas <linas@linas.org> *
5  * Copyright (C) 2000 Bill Gribble <grib@billgribble.com> *
6  * Copyright (c) 2006 David Hampton <hampton@employees.org> *
7  * *
8  * This program is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU General Public License as *
10  * published by the Free Software Foundation; either version 2 of *
11  * the License, or (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License*
19  * along with this program; if not, contact: *
20  * *
21  * Free Software Foundation Voice: +1-617-542-5942 *
22  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
23  * Boston, MA 02110-1301, USA gnu@gnu.org *
24  * *
25 \********************************************************************/
26 
27 #include "qofinstance.h"
28 #include <config.h>
29 
30 #include <platform.h>
31 #if PLATFORM(WINDOWS)
32 #include <windows.h>
33 #endif
34 
35 #include <glib.h>
36 #include <glib/gi18n.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #ifdef HAVE_SYS_TIME_H
40 # include <sys/time.h>
41 #endif
42 #include <time.h>
43 #ifdef HAVE_UNISTD_H
44 # include <unistd.h>
45 #endif
46 
47 #include "qof.h"
48 #include "qofbook.h"
49 #include "Split.h"
50 #include "AccountP.hpp"
51 #include "Account.hpp"
52 #include "Scrub.h"
53 #include "TransactionP.hpp"
54 #include "TransLog.h"
55 #include "cap-gains.h"
56 #include "gnc-commodity.h"
57 #include "gnc-engine.h"
58 #include "gnc-lot.h"
59 #include "gnc-event.h"
60 #include "qofinstance-p.h"
61 
62 const char *void_former_amt_str = "void-former-amount";
63 const char *void_former_val_str = "void-former-value";
64 
65 /* This static indicates the debugging module that this .o belongs to. */
66 static QofLogModule log_module = GNC_MOD_ENGINE;
67 
68 /* KVP key values used for SX info stored Split's slots. */
69 #define GNC_SX_ID "sched-xaction"
70 #define GNC_SX_ACCOUNT "account"
71 #define GNC_SX_CREDIT_FORMULA "credit-formula"
72 #define GNC_SX_DEBIT_FORMULA "debit-formula"
73 #define GNC_SX_CREDIT_NUMERIC "credit-numeric"
74 #define GNC_SX_DEBIT_NUMERIC "debit-numeric"
75 #define GNC_SX_SHARES "shares"
76 
77 enum
78 {
79  PROP_0,
80  PROP_TX, /* Table */
81  PROP_ACCOUNT, /* Table */
82  PROP_MEMO, /* Table */
83  PROP_ACTION, /* Table */
84 // PROP_RECONCILE_STATE, /* Table */
85  PROP_RECONCILE_DATE, /* Table */
86  PROP_VALUE, /* Table, in 2 fields */
87  PROP_SX_ACCOUNT, /* KVP */
88  PROP_SX_CREDIT_FORMULA, /* KVP */
89  PROP_SX_CREDIT_NUMERIC, /* KVP */
90  PROP_SX_DEBIT_FORMULA, /* KVP */
91  PROP_SX_DEBIT_NUMERIC, /* KVP */
92  PROP_SX_SHARES, /* KVP */
93  PROP_LOT, /* KVP */
94  PROP_ONLINE_ACCOUNT, /* KVP */
95  PROP_GAINS_SPLIT, /* KVP */
96  PROP_GAINS_SOURCE, /* KVP */
97  PROP_RUNTIME_0,
98  PROP_AMOUNT, /* Runtime */
99 
100 };
101 
102 static const char * split_type_normal = "normal";
103 static const char * split_type_stock_split = "stock-split";
104 
105 /* GObject Initialization */
106 G_DEFINE_TYPE(Split, gnc_split, QOF_TYPE_INSTANCE)
107 
108 static void
109 gnc_split_init(Split* split)
110 {
111  /* fill in some sane defaults */
112  split->acc = nullptr;
113  split->orig_acc = nullptr;
114  split->parent = nullptr;
115  split->lot = nullptr;
116 
117  split->action = CACHE_INSERT("");
118  split->memo = CACHE_INSERT("");
119  split->reconciled = NREC;
120  split->amount = gnc_numeric_zero();
121  split->value = gnc_numeric_zero();
122 
123  split->date_reconciled = 0;
124 
125  split->balance = gnc_numeric_zero();
126  split->cleared_balance = gnc_numeric_zero();
127  split->reconciled_balance = gnc_numeric_zero();
128  split->noclosing_balance = gnc_numeric_zero();
129 
130  split->gains = GAINS_STATUS_UNKNOWN;
131  split->gains_split = nullptr;
132 }
133 
134 static void
135 gnc_split_dispose(GObject *splitp)
136 {
137  G_OBJECT_CLASS(gnc_split_parent_class)->dispose(splitp);
138 }
139 
140 static void
141 gnc_split_finalize(GObject* splitp)
142 {
143  G_OBJECT_CLASS(gnc_split_parent_class)->finalize(splitp);
144 }
145 /* Note that g_value_set_object() refs the object, as does
146  * g_object_get(). But g_object_get() only unrefs once when it disgorges
147  * the object, leaving an unbalanced ref, which leaks. So instead of
148  * using g_value_set_object(), use g_value_take_object() which doesn't
149  * ref the object when used in get_property().
150  */
151 static void
152 gnc_split_get_property(GObject *object,
153  guint prop_id,
154  GValue *value,
155  GParamSpec *pspec)
156 {
157  Split *split;
158  Time64 t;
159 
160  g_return_if_fail(GNC_IS_SPLIT(object));
161 
162  split = GNC_SPLIT(object);
163  switch (prop_id)
164  {
165  case PROP_ACTION:
166  g_value_set_string(value, split->action);
167  break;
168  case PROP_MEMO:
169  g_value_set_string(value, split->memo);
170  break;
171  case PROP_VALUE:
172  g_value_set_boxed(value, &split->value);
173  break;
174  case PROP_AMOUNT:
175  g_value_set_boxed(value, &split->amount);
176  break;
177  case PROP_RECONCILE_DATE:
178  t.t = split->date_reconciled;
179  g_value_set_boxed(value, &t);
180  break;
181  case PROP_TX:
182  g_value_take_object(value, split->parent);
183  break;
184  case PROP_ACCOUNT:
185  g_value_take_object(value, split->acc);
186  break;
187  case PROP_LOT:
188  g_value_take_object(value, split->lot);
189  break;
190  case PROP_SX_CREDIT_FORMULA:
191  qof_instance_get_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_CREDIT_FORMULA);
192  break;
193  case PROP_SX_CREDIT_NUMERIC:
194  qof_instance_get_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_CREDIT_NUMERIC);
195  break;
196  case PROP_SX_DEBIT_FORMULA:
197  qof_instance_get_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_DEBIT_FORMULA);
198  break;
199  case PROP_SX_DEBIT_NUMERIC:
200  qof_instance_get_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_DEBIT_NUMERIC);
201  break;
202  case PROP_SX_ACCOUNT:
203  qof_instance_get_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_ACCOUNT);
204  break;
205  case PROP_SX_SHARES:
206  qof_instance_get_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_SHARES);
207  break;
208  case PROP_ONLINE_ACCOUNT:
209  qof_instance_get_kvp (QOF_INSTANCE (split), value, 1, "online_id");
210  break;
211  case PROP_GAINS_SPLIT:
212  qof_instance_get_kvp (QOF_INSTANCE (split), value, 1, "gains-split");
213  break;
214  case PROP_GAINS_SOURCE:
215  qof_instance_get_kvp (QOF_INSTANCE (split), value, 1, "gains-source");
216  break;
217  default:
218  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
219  break;
220  }
221 }
222 
223 static void
224 gnc_split_set_property(GObject *object,
225  guint prop_id,
226  const GValue *value,
227  GParamSpec *pspec)
228 {
229  Split *split;
230  gnc_numeric* number;
231  Time64 *t;
232  g_return_if_fail(GNC_IS_SPLIT(object));
233 
234  split = GNC_SPLIT(object);
235  if (prop_id < PROP_RUNTIME_0 && split->parent != nullptr)
236  g_assert (qof_instance_get_editlevel(split->parent));
237 
238  switch (prop_id)
239  {
240  case PROP_ACTION:
241  xaccSplitSetAction(split, g_value_get_string(value));
242  break;
243  case PROP_MEMO:
244  xaccSplitSetMemo(split, g_value_get_string(value));
245  break;
246  case PROP_VALUE:
247  number = static_cast<gnc_numeric*>(g_value_get_boxed(value));
248  xaccSplitSetValue(split, *number);
249  break;
250  case PROP_AMOUNT:
251  number = static_cast<gnc_numeric*>(g_value_get_boxed(value));
252  xaccSplitSetAmount(split, *number);
253  break;
254  case PROP_RECONCILE_DATE:
255  t = static_cast<Time64*>(g_value_get_boxed(value));
256  xaccSplitSetDateReconciledSecs(split, t->t);
257  break;
258  case PROP_TX:
259  xaccSplitSetParent(split, GNC_TRANSACTION(g_value_get_object(value)));
260  break;
261  case PROP_ACCOUNT:
262  xaccSplitSetAccount(split, GNC_ACCOUNT(g_value_get_object(value)));
263  break;
264  case PROP_LOT:
265  xaccSplitSetLot(split, GNC_LOT(g_value_get_object(value)));
266  break;
267  case PROP_SX_CREDIT_FORMULA:
268  qof_instance_set_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_CREDIT_FORMULA);
269  break;
270  case PROP_SX_CREDIT_NUMERIC:
271  qof_instance_set_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_CREDIT_NUMERIC);
272  break;
273  case PROP_SX_DEBIT_FORMULA:
274  qof_instance_set_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_DEBIT_FORMULA);
275  break;
276  case PROP_SX_DEBIT_NUMERIC:
277  qof_instance_set_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_DEBIT_NUMERIC);
278  break;
279  case PROP_SX_ACCOUNT:
280  qof_instance_set_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_ACCOUNT);
281  break;
282  case PROP_SX_SHARES:
283  qof_instance_set_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_SHARES);
284  break;
285  case PROP_ONLINE_ACCOUNT:
286  qof_instance_set_kvp (QOF_INSTANCE (split), value, 1, "online_id");
287  break;
288  case PROP_GAINS_SPLIT:
289  qof_instance_set_kvp (QOF_INSTANCE (split), value, 1, "gains-split");
290  break;
291  case PROP_GAINS_SOURCE:
292  qof_instance_set_kvp (QOF_INSTANCE (split), value, 1, "gains-source");
293  break;
294  default:
295  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
296  break;
297  }
298 }
299 
300 static void
301 gnc_split_class_init(SplitClass* klass)
302 {
303  GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
304 
305  gobject_class->dispose = gnc_split_dispose;
306  gobject_class->finalize = gnc_split_finalize;
307  gobject_class->set_property = gnc_split_set_property;
308  gobject_class->get_property = gnc_split_get_property;
309 
310  g_object_class_install_property
311  (gobject_class,
312  PROP_ACTION,
313  g_param_spec_string("action",
314  "Action",
315  "The action is an arbitrary string assigned "
316  "by the user. It is intended to be a short "
317  "string that contains extra information about "
318  "this split.",
319  nullptr,
320  G_PARAM_READWRITE));
321 
322  g_object_class_install_property
323  (gobject_class,
324  PROP_MEMO,
325  g_param_spec_string("memo",
326  "Memo",
327  "The action is an arbitrary string assigned "
328  "by the user. It is intended to be a short "
329  "string that describes the purpose of "
330  "this split.",
331  nullptr,
332  G_PARAM_READWRITE));
333 
334  g_object_class_install_property
335  (gobject_class,
336  PROP_VALUE,
337  g_param_spec_boxed("value",
338  "Split Value",
339  "The value for this split in the common currency. "
340  "The value and the amount provide enough information to "
341  "calculate a conversion rate.",
342  GNC_TYPE_NUMERIC,
343  G_PARAM_READWRITE));
344 
345  g_object_class_install_property
346  (gobject_class,
347  PROP_AMOUNT,
348  g_param_spec_boxed("amount",
349  "Split Amount",
350  "The value for this split in the currency of its account. "
351  "The value and the amount provide enough information to "
352  "calculate a conversion rate.",
353  GNC_TYPE_NUMERIC,
354  G_PARAM_READWRITE));
355 
356  g_object_class_install_property
357  (gobject_class,
358  PROP_RECONCILE_DATE,
359  g_param_spec_boxed("reconcile-date",
360  "Reconcile Date",
361  "The date this split was reconciled.",
362  GNC_TYPE_TIME64,
363  G_PARAM_READWRITE));
364 
365  g_object_class_install_property
366  (gobject_class,
367  PROP_TX,
368  g_param_spec_object ("transaction",
369  "Transaction",
370  "The transaction that this split belongs to.",
371  GNC_TYPE_TRANSACTION,
372  G_PARAM_READWRITE));
373 
374  g_object_class_install_property
375  (gobject_class,
376  PROP_ACCOUNT,
377  g_param_spec_object ("account",
378  "Account",
379  "The account that this split belongs to.",
380  GNC_TYPE_ACCOUNT,
381  G_PARAM_READWRITE));
382 
383  g_object_class_install_property
384  (gobject_class,
385  PROP_LOT,
386  g_param_spec_object ("lot",
387  "Lot",
388  "The lot that this split belongs to.",
389  GNC_TYPE_LOT,
390  G_PARAM_READWRITE));
391 
392  g_object_class_install_property
393  (gobject_class,
394  PROP_SX_DEBIT_FORMULA,
395  g_param_spec_string("sx-debit-formula",
396  "Schedule Transaction Debit Formula",
397  "The formula used to calculate the actual debit "
398  "amount when a real split is generated from this "
399  "SX split.",
400  nullptr,
401  G_PARAM_READWRITE));
402 
403  g_object_class_install_property
404  (gobject_class,
405  PROP_SX_DEBIT_NUMERIC,
406  g_param_spec_boxed("sx-debit-numeric",
407  "Scheduled Transaction Debit Numeric",
408  "Numeric value to plug into the Debit Formula when a "
409  "real split is generated from this SX split.",
410  GNC_TYPE_NUMERIC,
411  G_PARAM_READWRITE));
412 
413  g_object_class_install_property
414  (gobject_class,
415  PROP_SX_CREDIT_FORMULA,
416  g_param_spec_string("sx-credit-formula",
417  "Schedule Transaction Credit Formula",
418  "The formula used to calculate the actual credit "
419  "amount when a real split is generated from this "
420  "SX split.",
421  nullptr,
422  G_PARAM_READWRITE));
423 
424  g_object_class_install_property
425  (gobject_class,
426  PROP_SX_CREDIT_NUMERIC,
427  g_param_spec_boxed("sx-credit-numeric",
428  "Scheduled Transaction Credit Numeric",
429  "Numeric value to plug into the Credit Formula when a "
430  "real split is generated from this SX split.",
431  GNC_TYPE_NUMERIC,
432  G_PARAM_READWRITE));
433 /* FIXME: PROP_SX_SHARES should be stored as a gnc_numeric, but the function
434  * which uses it, gnc_template_register_save_shares_cell, stores a
435  * phony string. This is maintained until backwards compatibility can
436  * be established.
437  */
438  g_object_class_install_property
439  (gobject_class,
440  PROP_SX_SHARES,
441  g_param_spec_string("sx-shares",
442  "Scheduled Transaction Shares",
443  "Numeric value of shares to insert in a new split when "
444  "it's generated from this SX split.",
445  nullptr,
446  G_PARAM_READWRITE));
447 
448  g_object_class_install_property
449  (gobject_class,
450  PROP_SX_ACCOUNT,
451  g_param_spec_boxed("sx-account",
452  "Scheduled Transaction Account",
453  "The target account for a scheduled transaction split.",
454  GNC_TYPE_GUID,
455  G_PARAM_READWRITE));
456 
457  g_object_class_install_property
458  (gobject_class,
459  PROP_ONLINE_ACCOUNT,
460  g_param_spec_string ("online-id",
461  "Online Account ID",
462  "The online account which corresponds to this "
463  "account for OFX/HCBI import",
464  nullptr,
465  G_PARAM_READWRITE));
466 
467  g_object_class_install_property
468  (gobject_class,
469  PROP_GAINS_SPLIT,
470  g_param_spec_boxed ("gains-split",
471  "Gains Split",
472  "The capital gains split associated with this "
473  "split when this split represents the proceeds "
474  "from the sale of a commodity inside a Lot.",
475  GNC_TYPE_GUID,
476  G_PARAM_READWRITE));
477 
478  g_object_class_install_property
479  (gobject_class,
480  PROP_GAINS_SOURCE,
481  g_param_spec_boxed ("gains-source",
482  "Gains Source",
483  "The source split for which this split this is "
484  "the gains split. ",
485  GNC_TYPE_GUID,
486  G_PARAM_READWRITE));
487 }
488 
489 /********************************************************************\
490  * xaccInitSplit
491  * Initialize a Split structure
492 \********************************************************************/
493 
494 static void
495 xaccInitSplit(Split * split, QofBook *book)
496 {
497  qof_instance_init_data(&split->inst, GNC_ID_SPLIT, book);
498 }
499 
500 void
501 xaccSplitReinit(Split * split)
502 {
503  /* fill in some sane defaults */
504  split->acc = nullptr;
505  split->orig_acc = nullptr;
506  split->parent = nullptr;
507  split->lot = nullptr;
508 
509  CACHE_REPLACE(split->action, "");
510  CACHE_REPLACE(split->memo, "");
511  split->reconciled = NREC;
512  split->amount = gnc_numeric_zero();
513  split->value = gnc_numeric_zero();
514 
515  split->date_reconciled = 0;
516 
517  split->balance = gnc_numeric_zero();
518  split->cleared_balance = gnc_numeric_zero();
519  split->reconciled_balance = gnc_numeric_zero();
520  split->noclosing_balance = gnc_numeric_zero();
521 
522  qof_instance_set_idata(split, 0);
523 
524  split->gains = GAINS_STATUS_UNKNOWN;
525  split->gains_split = nullptr;
526 }
527 
528 /********************************************************************\
529 \********************************************************************/
530 
531 Split *
532 xaccMallocSplit(QofBook *book)
533 {
534  Split *split;
535  g_return_val_if_fail (book, nullptr);
536 
537  split = GNC_SPLIT(g_object_new (GNC_TYPE_SPLIT, nullptr));
538  xaccInitSplit (split, book);
539 
540  return split;
541 }
542 
543 /********************************************************************\
544 \********************************************************************/
545 /* This routine is not exposed externally, since it does weird things,
546  * like not really setting up the parent account correctly, and ditto
547  * the parent transaction. This routine is prone to programmer error
548  * if not used correctly. It is used only by the edit-rollback code.
549  * Don't get duped!
550  */
551 
552 Split *
553 xaccDupeSplit (const Split *s)
554 {
555  Split *split = GNC_SPLIT(g_object_new (GNC_TYPE_SPLIT, nullptr));
556 
557  /* Trash the entity table. We don't want to mistake the cloned
558  * splits as something official. If we ever use this split, we'll
559  * have to fix this up.
560  */
561  split->inst.e_type = nullptr;
562  qof_instance_copy_guid(split, s);
563  qof_instance_copy_book(split, s);
564 
565  split->parent = s->parent;
566  split->acc = s->acc;
567  split->orig_acc = s->orig_acc;
568  split->lot = s->lot;
569 
570  CACHE_REPLACE(split->memo, s->memo);
571  CACHE_REPLACE(split->action, s->action);
572 
573  qof_instance_copy_kvp (QOF_INSTANCE (split), QOF_INSTANCE (s));
574 
575  split->reconciled = s->reconciled;
576  split->date_reconciled = s->date_reconciled;
577 
578  split->value = s->value;
579  split->amount = s->amount;
580 
581  /* no need to futz with the balances; these get wiped each time ...
582  * split->balance = s->balance;
583  * split->cleared_balance = s->cleared_balance;
584  * split->reconciled_balance = s->reconciled_balance;
585  */
586 
587  return split;
588 }
589 
590 Split *
591 xaccSplitCloneNoKvp (const Split *s)
592 {
593  Split *split = GNC_SPLIT(g_object_new (GNC_TYPE_SPLIT, nullptr));
594 
595  split->parent = nullptr;
596  split->memo = CACHE_INSERT(s->memo);
597  split->action = CACHE_INSERT(s->action);
598  split->reconciled = s->reconciled;
599  split->date_reconciled = s->date_reconciled;
600  split->value = s->value;
601  split->amount = s->amount;
602  split->balance = s->balance;
603  split->cleared_balance = s->cleared_balance;
604  split->reconciled_balance = s->reconciled_balance;
605  split->noclosing_balance = s->noclosing_balance;
606 
607  split->gains = GAINS_STATUS_UNKNOWN;
608  split->gains_split = nullptr;
609 
610  qof_instance_init_data(&split->inst, GNC_ID_SPLIT,
612  xaccAccountInsertSplit(s->acc, split);
613  if (s->lot)
614  {
615  /* CHECKME: Is this right? */
616  gnc_lot_add_split(s->lot, split);
617  }
618  return split;
619 }
620 
621 void
622 xaccSplitCopyKvp (const Split *from, Split *to)
623 {
624  qof_instance_copy_kvp (QOF_INSTANCE (to), QOF_INSTANCE (from));
625  /* But not the online-id */
626  qof_instance_set (QOF_INSTANCE (to), "online-id", nullptr, nullptr);
627 }
628 
629 /*################## Added for Reg2 #################*/
630 
631 /* This is really a helper for xaccTransCopyOnto. It doesn't reparent
632  the 'to' split to from's transaction, because xaccTransCopyOnto is
633  responsible for parenting the split to the correct transaction.
634  Also, from's parent transaction may not even be a valid
635  transaction, so this function may not modify anything about 'from'
636  or from's transaction.
637 */
638 void
639 xaccSplitCopyOnto(const Split *from_split, Split *to_split)
640 {
641  if (!from_split || !to_split) return;
642  xaccTransBeginEdit (to_split->parent);
643 
644  xaccSplitSetMemo(to_split, xaccSplitGetMemo(from_split));
645  xaccSplitSetAction(to_split, xaccSplitGetAction(from_split));
646  xaccSplitSetAmount(to_split, xaccSplitGetAmount(from_split));
647  xaccSplitSetValue(to_split, xaccSplitGetValue(from_split));
648  /* Setting the account is okay here because, even though the from
649  split might not really belong to the account it claims to,
650  setting the account won't cause any event involving from. */
651  xaccSplitSetAccount(to_split, xaccSplitGetAccount(from_split));
652  /* N.B. Don't set parent. */
653 
654  qof_instance_set_dirty(QOF_INSTANCE(to_split));
655  xaccTransCommitEdit(to_split->parent);
656 }
657 
658 /*################## Added for Reg2 #################*/
659 
660 
661 #ifdef DUMP_FUNCTIONS
662 void
663 xaccSplitDump (const Split *split, const char *tag)
664 {
665  char datebuff[MAX_DATE_LENGTH + 1];
666  memset (datebuff, 0, sizeof(datebuff));
667  qof_print_date_buff (datebuff, MAX_DATE_LENGTH, split->date_reconciled);
668  printf(" %s Split %p", tag, split);
669  printf(" Book: %p\n", qof_instance_get_book(split));
670  printf(" Account: %p (%s)\n", split->acc,
671  split->acc ? xaccAccountGetName(split->acc) : "");
672  printf(" Commod: %s\n",
673  split->acc ?
675  : "");
676  printf(" Lot: %p\n", split->lot);
677  printf(" Parent: %p\n", split->parent);
678  printf(" Gains: %p\n", split->gains_split);
679  printf(" Memo: %s\n", split->memo ? split->memo : "(null)");
680  printf(" Action: %s\n", split->action ? split->action : "(null)");
681  printf(" KVP Data: %s\n", qof_instance_kvp_as_string (QOF_INSTANCE (split)));
682  printf(" Recncld: %c (date %s)\n", split->reconciled, datebuff);
683 
684  printf(" Value: %s\n", gnc_numeric_to_string(split->value));
685  printf(" Amount: %s\n", gnc_numeric_to_string(split->amount));
686  printf(" Balance: %s\n", gnc_numeric_to_string(split->balance));
687  printf(" CBalance: %s\n", gnc_numeric_to_string(split->cleared_balance));
688  printf(" RBalance: %s\n",
689  gnc_numeric_to_string(split->reconciled_balance));
690  printf(" NoClose: %s\n", gnc_numeric_to_string(split->noclosing_balance));
691  printf(" idata: %x\n", qof_instance_get_idata(split));
692 }
693 #endif
694 
695 /********************************************************************\
696 \********************************************************************/
697 static void
698 do_destroy (QofInstance *inst)
699 {
700  xaccFreeSplit (GNC_SPLIT (inst));
701 }
702 
703 void
704 xaccFreeSplit (Split *split)
705 {
706  if (!split) return;
707 
708  /* Debug double-free's */
709  if (((char *) 1) == split->memo)
710  {
711  PERR ("double-free %p", split);
712  return;
713  }
714  CACHE_REMOVE(split->memo);
715  CACHE_REMOVE(split->action);
716 
717  if (split->inst.e_type) /* Don't do this for dupe splits. */
718  {
719  /* gnc_lot_remove_split needs the account, so do it first. */
720  if (GNC_IS_LOT (split->lot) && !qof_instance_get_destroying (QOF_INSTANCE (split->lot)))
721  gnc_lot_remove_split (split->lot, split);
722  if (GNC_IS_ACCOUNT (split->acc)
723  && !qof_instance_get_destroying (QOF_INSTANCE (split->acc)))
724  {
725  gnc_account_remove_split (split->acc, split);
726  /* gnc_float_split_to_split generates a qof_event_gen via
727  * xaccAccountCommitEdit even though it doesn't touch the
728  * account. That causes QofQueryViews to notice the split
729  * even though it isn't added to the account. We need a
730  * countervailing event so that they'll notice it's not
731  * there any more.
732  */
733  qof_event_gen(&split->acc->inst, QOF_EVENT_MODIFY, nullptr);
734  }
735  /* We should do the same for split->parent but we might be getting
736  * called from xaccFreeTransaction and that would cause trouble.
737  */
738  }
739 
740  /* Just in case someone looks up freed memory ... */
741  split->memo = (char *) 1;
742  split->action = nullptr;
743  split->reconciled = NREC;
744  split->amount = gnc_numeric_zero();
745  split->value = gnc_numeric_zero();
746  split->parent = nullptr;
747  split->lot = nullptr;
748  split->acc = nullptr;
749  split->orig_acc = nullptr;
750 
751  split->date_reconciled = 0;
752  G_OBJECT_CLASS (QOF_INSTANCE_GET_CLASS (&split->inst))->dispose(G_OBJECT (split));
753 
754  if (split->gains_split)
755  {
756  Split *other = xaccSplitGetOtherSplit(split->gains_split);
757  split->gains_split->gains_split = nullptr;
758  if (other)
759  other->gains_split = nullptr;
760  }
761 
762  g_object_unref(split);
763 }
764 
765 void mark_split (Split *s)
766 {
767  if (s->acc)
768  {
769  g_object_set(s->acc, "sort-dirty", TRUE, "balance-dirty", TRUE, nullptr);
770  }
771 
772  /* set dirty flag on lot too. */
773  if (s->lot) gnc_lot_set_closed_unknown(s->lot);
774 }
775 
776 /*
777  * Helper routine for xaccSplitEqual.
778  */
779 static gboolean
780 xaccSplitEqualCheckBal (const char *tag, gnc_numeric a, gnc_numeric b)
781 {
782  char *str_a, *str_b;
783 
784  if (gnc_numeric_equal (a, b))
785  return TRUE;
786 
787  str_a = gnc_numeric_to_string (a);
788  str_b = gnc_numeric_to_string (b);
789 
790  PINFO ("%sbalances differ: %s vs %s", tag, str_a, str_b);
791 
792  g_free (str_a);
793  g_free (str_b);
794 
795  return FALSE;
796 }
797 
798 /********************************************************************
799  * xaccSplitEqual
800  ********************************************************************/
801 gboolean
802 xaccSplitEqual(const Split *sa, const Split *sb,
803  gboolean check_guids,
804  gboolean check_balances,
805  gboolean check_txn_splits)
806 {
807  gboolean same_book;
808 
809  if (!sa && !sb) return TRUE; /* Arguable. FALSE is better, methinks */
810 
811  if (!sa || !sb)
812  {
813  PINFO ("one is nullptr");
814  return FALSE;
815  }
816 
817  if (sa == sb) return TRUE;
818 
819  same_book = qof_instance_get_book(QOF_INSTANCE(sa)) == qof_instance_get_book(QOF_INSTANCE(sb));
820 
821  if (check_guids)
822  {
823  if (qof_instance_guid_compare(sa, sb) != 0)
824  {
825  PINFO ("GUIDs differ");
826  return FALSE;
827  }
828  }
829 
830  /* If the same book, since these strings are cached we can just use pointer equality */
831  if ((same_book && sa->memo != sb->memo) || (!same_book && g_strcmp0(sa->memo, sb->memo) != 0))
832  {
833  PINFO ("memos differ: (%p)%s vs (%p)%s",
834  sa->memo, sa->memo, sb->memo, sb->memo);
835  return FALSE;
836  }
837 
838  if ((same_book && sa->action != sb->action) || (!same_book && g_strcmp0(sa->action, sb->action) != 0))
839  {
840  PINFO ("actions differ: %s vs %s", sa->action, sb->action);
841  return FALSE;
842  }
843 
844  if (qof_instance_compare_kvp (QOF_INSTANCE (sa), QOF_INSTANCE (sb)) != 0)
845  {
846  char *frame_a;
847  char *frame_b;
848 
849  frame_a = qof_instance_kvp_as_string (QOF_INSTANCE (sa));
850  frame_b = qof_instance_kvp_as_string (QOF_INSTANCE (sb));
851 
852  PINFO ("kvp frames differ:\n%s\n\nvs\n\n%s", frame_a, frame_b);
853 
854  g_free (frame_a);
855  g_free (frame_b);
856 
857  return FALSE;
858  }
859 
860  if (sa->reconciled != sb->reconciled)
861  {
862  PINFO ("reconcile flags differ: %c vs %c", sa->reconciled, sb->reconciled);
863  return FALSE;
864  }
865 
866  if (sa->date_reconciled != sb->date_reconciled)
867  {
868  PINFO ("reconciled date differs");
869  return FALSE;
870  }
871 
873  {
874  char *str_a;
875  char *str_b;
876 
879 
880  PINFO ("amounts differ: %s vs %s", str_a, str_b);
881 
882  g_free (str_a);
883  g_free (str_b);
884 
885  return FALSE;
886  }
887 
889  {
890  char *str_a;
891  char *str_b;
892 
895 
896  PINFO ("values differ: %s vs %s", str_a, str_b);
897 
898  g_free (str_a);
899  g_free (str_b);
900 
901  return FALSE;
902  }
903 
904  if (check_balances)
905  {
906  if (!xaccSplitEqualCheckBal ("", sa->balance, sb->balance))
907  return FALSE;
908  if (!xaccSplitEqualCheckBal ("cleared ", sa->cleared_balance,
909  sb->cleared_balance))
910  return FALSE;
911  if (!xaccSplitEqualCheckBal ("reconciled ", sa->reconciled_balance,
912  sb->reconciled_balance))
913  return FALSE;
914  if (!xaccSplitEqualCheckBal ("noclosing ", sa->noclosing_balance,
915  sb->noclosing_balance))
916  return FALSE;
917  }
918 
919  if (!xaccTransEqual(sa->parent, sb->parent, check_guids, check_txn_splits,
920  check_balances, FALSE))
921  {
922  PINFO ("transactions differ");
923  return FALSE;
924  }
925 
926  return TRUE;
927 }
928 
929 
930 
931 /********************************************************************
932  * Account funcs
933  ********************************************************************/
934 
935 Account *
936 xaccSplitGetAccount (const Split *s)
937 {
938  return s ? s->acc : nullptr;
939 }
940 
941 void
942 xaccSplitSetAccount (Split *s, Account *acc)
943 {
944  Transaction *trans;
945 
946  g_return_if_fail(s && acc);
947  g_return_if_fail(qof_instance_books_equal(acc, s));
948 
949  trans = s->parent;
950  if (trans)
951  xaccTransBeginEdit(trans);
952 
953  s->acc = acc;
954  qof_instance_set_dirty(QOF_INSTANCE(s));
955 
956  if (trans)
957  xaccTransCommitEdit(trans);
958 }
959 
960 static void commit_err (QofInstance *inst, QofBackendError errcode)
961 {
962  PERR("commit error: %d", errcode);
963  gnc_engine_signal_commit_error( errcode );
964 }
965 
966 /* An engine-private helper for completing xaccTransCommitEdit(). */
967 void
968 xaccSplitCommitEdit(Split *s)
969 {
970  Account *acc = nullptr;
971  Account *orig_acc = nullptr;
972 
973  g_return_if_fail(s);
974  if (!qof_instance_is_dirty(QOF_INSTANCE(s)))
975  return;
976 
977  orig_acc = s->orig_acc;
978 
979  if (GNC_IS_ACCOUNT(s->acc))
980  acc = s->acc;
981 
982  /* Remove from lot (but only if it hasn't been moved to
983  new lot already) */
984  if (s->lot && (gnc_lot_get_account(s->lot) != acc || qof_instance_get_destroying(s)))
985  gnc_lot_remove_split (s->lot, s);
986 
987  /* Possibly remove the split from the original account... */
988  if (orig_acc && (orig_acc != acc || qof_instance_get_destroying(s)))
989  {
990  if (!gnc_account_remove_split(orig_acc, s))
991  {
992  PERR("Account lost track of moved or deleted split.");
993  }
994  }
995 
996  /* ... and insert it into the new account if needed */
997  if (acc && (orig_acc != acc) && !qof_instance_get_destroying(s))
998  {
999  if (gnc_account_insert_split(acc, s))
1000  {
1001  /* If the split's lot belonged to some other account, we
1002  leave it so. */
1003  if (s->lot && (nullptr == gnc_lot_get_account(s->lot)))
1004  xaccAccountInsertLot (acc, s->lot);
1005  }
1006  else
1007  {
1008  PERR("Account grabbed split prematurely.");
1009  }
1011  }
1012 
1013  if (s->parent != s->orig_parent)
1014  {
1015  //FIXME: find better event
1016  if (s->orig_parent)
1017  qof_event_gen(&s->orig_parent->inst, QOF_EVENT_MODIFY,
1018  nullptr);
1019  }
1020  if (s->lot)
1021  {
1022  /* A change of value/amnt affects gains display, etc. */
1023  qof_event_gen (QOF_INSTANCE(s->lot), QOF_EVENT_MODIFY, nullptr);
1024  }
1025 
1026  /* Important: we save off the original parent transaction and account
1027  so that when we commit, we can generate signals for both the
1028  original and new transactions, for the _next_ begin/commit cycle. */
1029  s->orig_acc = s->acc;
1030  s->orig_parent = s->parent;
1031  if (!qof_commit_edit_part2(QOF_INSTANCE(s), commit_err, nullptr, do_destroy))
1032  return;
1033 
1034  if (acc)
1035  {
1036  g_object_set(acc, "sort-dirty", TRUE, "balance-dirty", TRUE, nullptr);
1038  }
1039 }
1040 
1041 /* An engine-private helper for completing xaccTransRollbackEdit(). */
1042 void
1043 xaccSplitRollbackEdit(Split *s)
1044 {
1045 
1046  /* Don't use setters because we want to allow nullptr. This is legit
1047  only because we don't emit events for changing accounts until
1048  the final commit. */
1049  if (s->acc != s->orig_acc)
1050  s->acc = s->orig_acc;
1051 
1052  /* Undestroy if needed */
1053  if (qof_instance_get_destroying(s) && s->parent)
1054  {
1055  GncEventData ed;
1056  qof_instance_set_destroying(s, FALSE);
1057  ed.node = s;
1058  ed.idx = -1; /* unused */
1059  qof_event_gen(&s->parent->inst, GNC_EVENT_ITEM_ADDED, &ed);
1060  }
1061 
1062  /* But for the parent trans, we want the intermediate events, so
1063  we use the setter. */
1064  xaccSplitSetParent(s, s->orig_parent);
1065 }
1066 
1067 /********************************************************************\
1068 \********************************************************************/
1069 
1070 Split *
1071 xaccSplitLookup (const GncGUID *guid, QofBook *book)
1072 {
1073  QofCollection *col;
1074  if (!guid || !book) return nullptr;
1075  col = qof_book_get_collection (book, GNC_ID_SPLIT);
1076  return (Split *) qof_collection_lookup_entity (col, guid);
1077 }
1078 
1079 /********************************************************************\
1080 \********************************************************************/
1081 /* Routines for marking splits dirty, and for sending out change
1082  * events. Note that we can't just mark-n-generate-event in one
1083  * step, since sometimes we need to mark things up before its suitable
1084  * to send out a change event.
1085  */
1086 
1087 /* CHECKME: This function modifies the Split without dirtying or
1088  checking its parent. Is that correct? */
1089 void
1090 xaccSplitDetermineGainStatus (Split *split)
1091 {
1092  Split *other;
1093  GValue v = G_VALUE_INIT;
1094  GncGUID *guid = nullptr;
1095 
1096  if (GAINS_STATUS_UNKNOWN != split->gains) return;
1097 
1098  other = xaccSplitGetCapGainsSplit (split);
1099  if (other)
1100  {
1101  split->gains = GAINS_STATUS_A_VDIRTY | GAINS_STATUS_DATE_DIRTY;
1102  split->gains_split = other;
1103  return;
1104  }
1105 
1106  qof_instance_get_kvp (QOF_INSTANCE (split), &v, 1, "gains-source");
1107  if (G_VALUE_HOLDS_BOXED (&v))
1108  guid = (GncGUID*)g_value_get_boxed (&v);
1109  if (!guid)
1110  {
1111  // CHECKME: We leave split->gains_split alone. Is that correct?
1112  split->gains = GAINS_STATUS_A_VDIRTY | GAINS_STATUS_DATE_DIRTY;
1113  }
1114  else
1115  {
1116  QofCollection *col;
1118  GNC_ID_SPLIT);
1119  split->gains = GAINS_STATUS_GAINS;
1120  other = (Split *) qof_collection_lookup_entity (col, guid);
1121  split->gains_split = other;
1122  }
1123  g_value_unset (&v);
1124 }
1125 
1126 /********************************************************************\
1127 \********************************************************************/
1128 
1129 static inline int
1130 get_currency_denom(const Split * s)
1131 {
1132  if (!(s && s->parent && s->parent->common_currency))
1133  {
1134  return GNC_DENOM_AUTO;
1135  }
1136  else
1137  {
1138  return gnc_commodity_get_fraction (s->parent->common_currency);
1139  }
1140 }
1141 
1142 static inline int
1143 get_commodity_denom(const Split * s)
1144 {
1145  if (!(s && s->acc))
1146  {
1147  return GNC_DENOM_AUTO;
1148  }
1149  else
1150  {
1151  return xaccAccountGetCommoditySCU(s->acc);
1152  }
1153 }
1154 
1155 /********************************************************************\
1156 \********************************************************************/
1157 
1158 void
1159 xaccSplitSetSharePriceAndAmount (Split *s, gnc_numeric price, gnc_numeric amt)
1160 {
1161  if (!s) return;
1162  ENTER (" ");
1163  xaccTransBeginEdit (s->parent);
1164 
1165  s->amount = gnc_numeric_convert(amt, get_commodity_denom(s),
1167  s->value = gnc_numeric_mul(s->amount, price,
1168  get_currency_denom(s), GNC_HOW_RND_ROUND_HALF_UP);
1169 
1170  SET_GAINS_A_VDIRTY(s);
1171  mark_split (s);
1172  qof_instance_set_dirty(QOF_INSTANCE(s));
1173  xaccTransCommitEdit(s->parent);
1174  LEAVE ("");
1175 }
1176 
1177 static void
1178 qofSplitSetSharePrice (Split *split, gnc_numeric price)
1179 {
1180  g_return_if_fail(split);
1181  split->value = gnc_numeric_mul(xaccSplitGetAmount(split),
1182  price, get_currency_denom(split),
1184 }
1185 
1186 void
1187 xaccSplitSetSharePrice (Split *s, gnc_numeric price)
1188 {
1189  if (!s) return;
1190 
1191  if (gnc_numeric_zero_p (price))
1192  return;
1193 
1194  ENTER (" ");
1195  xaccTransBeginEdit (s->parent);
1196 
1197  s->value = gnc_numeric_mul(xaccSplitGetAmount(s),
1198  price, get_currency_denom(s),
1200 
1201  SET_GAINS_VDIRTY(s);
1202  mark_split (s);
1203  qof_instance_set_dirty(QOF_INSTANCE(s));
1204  xaccTransCommitEdit(s->parent);
1205  LEAVE ("");
1206 }
1207 
1208 static void
1209 qofSplitSetAmount (Split *split, gnc_numeric amt)
1210 {
1211  g_return_if_fail(split);
1212  if (split->acc)
1213  {
1214  split->amount = gnc_numeric_convert(amt,
1215  get_commodity_denom(split), GNC_HOW_RND_ROUND_HALF_UP);
1216  }
1217  else
1218  {
1219  split->amount = amt;
1220  }
1221 }
1222 
1223 /* The amount of the split in the _account's_ commodity. */
1224 void
1225 xaccSplitSetAmount (Split *s, gnc_numeric amt)
1226 {
1227  if (!s) return;
1228  g_return_if_fail(gnc_numeric_check(amt) == GNC_ERROR_OK);
1229  ENTER ("(split=%p) old amt=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT
1230  " new amt=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, s,
1231  s->amount.num, s->amount.denom, amt.num, amt.denom);
1232 
1233  xaccTransBeginEdit (s->parent);
1234  if (s->acc)
1235  {
1236  s->amount = gnc_numeric_convert(amt, get_commodity_denom(s),
1238  g_assert (gnc_numeric_check (s->amount) == GNC_ERROR_OK);
1239  }
1240  else
1241  s->amount = amt;
1242 
1243  SET_GAINS_ADIRTY(s);
1244  mark_split (s);
1245  qof_instance_set_dirty(QOF_INSTANCE(s));
1246  xaccTransCommitEdit(s->parent);
1247  LEAVE("");
1248 }
1249 
1250 static void
1251 qofSplitSetValue (Split *split, gnc_numeric amt)
1252 {
1253  g_return_if_fail(split);
1254  split->value = gnc_numeric_convert(amt,
1255  get_currency_denom(split), GNC_HOW_RND_ROUND_HALF_UP);
1256  g_assert(gnc_numeric_check (split->value) != GNC_ERROR_OK);
1257 }
1258 
1259 /* The value of the split in the _transaction's_ currency. */
1260 void
1261 xaccSplitSetValue (Split *s, gnc_numeric amt)
1262 {
1263  gnc_numeric new_val;
1264  if (!s) return;
1265 
1266  g_return_if_fail(gnc_numeric_check(amt) == GNC_ERROR_OK);
1267  ENTER ("(split=%p) old val=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT
1268  " new val=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, s,
1269  s->value.num, s->value.denom, amt.num, amt.denom);
1270 
1271  xaccTransBeginEdit (s->parent);
1272  new_val = gnc_numeric_convert(amt, get_currency_denom(s),
1274  if (gnc_numeric_check(new_val) == GNC_ERROR_OK &&
1275  !(gnc_numeric_zero_p (new_val) && !gnc_numeric_zero_p (amt)))
1276  {
1277  s->value = new_val;
1278  }
1279  else
1280  {
1281  PERR("numeric error %s in converting the split value's denominator with amount %s and denom %d",
1283  gnc_num_dbg_to_string (amt), get_currency_denom(s));
1284  }
1285 
1286  SET_GAINS_VDIRTY(s);
1287  mark_split (s);
1288  qof_instance_set_dirty(QOF_INSTANCE(s));
1289  xaccTransCommitEdit(s->parent);
1290  LEAVE ("");
1291 }
1292 
1293 /********************************************************************\
1294 \********************************************************************/
1295 
1296 gnc_numeric
1297 xaccSplitGetBalance (const Split *s)
1298 {
1299  return s ? s->balance : gnc_numeric_zero();
1300 }
1301 
1302 gnc_numeric
1304 {
1305  return s ? s->noclosing_balance : gnc_numeric_zero();
1306 }
1307 
1308 gnc_numeric
1310 {
1311  return s ? s->cleared_balance : gnc_numeric_zero();
1312 }
1313 
1314 gnc_numeric
1316 {
1317  return s ? s->reconciled_balance : gnc_numeric_zero();
1318 }
1319 
1320 void
1321 xaccSplitSetBaseValue (Split *s, gnc_numeric value,
1322  const gnc_commodity * base_currency)
1323 {
1324  const gnc_commodity *currency;
1325  const gnc_commodity *commodity;
1326 
1327  if (!s) return;
1328  xaccTransBeginEdit (s->parent);
1329 
1330  if (!s->acc)
1331  {
1332  PERR ("split must have a parent account");
1333  return;
1334  }
1335 
1336  currency = xaccTransGetCurrency (s->parent);
1337  commodity = xaccAccountGetCommodity (s->acc);
1338 
1339  /* If the base_currency is the transaction's commodity ('currency'),
1340  * set the value. If it's the account commodity, set the
1341  * amount. If both, set both. */
1342  if (gnc_commodity_equiv(currency, base_currency))
1343  {
1344  if (gnc_commodity_equiv(commodity, base_currency))
1345  {
1346  s->amount = gnc_numeric_convert(value,
1347  get_commodity_denom(s),
1349  }
1350  s->value = gnc_numeric_convert(value,
1351  get_currency_denom(s),
1353  }
1354  else if (gnc_commodity_equiv(commodity, base_currency))
1355  {
1356  s->amount = gnc_numeric_convert(value, get_commodity_denom(s),
1358  }
1359  else
1360  {
1361  PERR ("inappropriate base currency %s "
1362  "given split currency=%s and commodity=%s\n",
1363  gnc_commodity_get_printname(base_currency),
1364  gnc_commodity_get_printname(currency),
1365  gnc_commodity_get_printname(commodity));
1366  return;
1367  }
1368 
1369  SET_GAINS_A_VDIRTY(s);
1370  mark_split (s);
1371  qof_instance_set_dirty(QOF_INSTANCE(s));
1372  xaccTransCommitEdit(s->parent);
1373 }
1374 
1375 gnc_numeric
1376 xaccSplitGetBaseValue (const Split *s, const gnc_commodity * base_currency)
1377 {
1378  if (!s || !s->acc || !s->parent) return gnc_numeric_zero();
1379 
1380  /* be more precise -- the value depends on the currency we want it
1381  * expressed in. */
1382  if (gnc_commodity_equiv(xaccTransGetCurrency(s->parent), base_currency))
1383  return xaccSplitGetValue(s);
1384  if (gnc_commodity_equiv(xaccAccountGetCommodity(s->acc), base_currency))
1385  return xaccSplitGetAmount(s);
1386 
1387  PERR ("inappropriate base currency %s "
1388  "given split currency=%s and commodity=%s\n",
1389  gnc_commodity_get_printname(base_currency),
1392  return gnc_numeric_zero();
1393 }
1394 
1395 /********************************************************************\
1396 \********************************************************************/
1397 
1398 gnc_numeric
1399 xaccSplitConvertAmount (const Split *split, const Account * account)
1400 {
1401  gnc_commodity *acc_com, *to_commodity;
1402  Transaction *txn;
1403  gnc_numeric amount, value, convrate;
1404  Account * split_acc;
1405 
1406  amount = xaccSplitGetAmount (split);
1407 
1408  /* If this split is attached to this account, OR */
1409  split_acc = xaccSplitGetAccount (split);
1410  if (split_acc == account)
1411  return amount;
1412 
1413  /* If split->account->commodity == to_commodity, return the amount */
1414  acc_com = xaccAccountGetCommodity (split_acc);
1415  to_commodity = xaccAccountGetCommodity (account);
1416  if (acc_com && gnc_commodity_equal (acc_com, to_commodity))
1417  return amount;
1418 
1419  /* Ok, this split is not for the viewed account, and the commodity
1420  * does not match. So we need to do some conversion.
1421  *
1422  * First, we can cheat. If this transaction is balanced and has
1423  * exactly two splits, then we can implicitly determine the exchange
1424  * rate and just return the 'other' split amount.
1425  */
1426  txn = xaccSplitGetParent (split);
1427  if (txn && xaccTransIsBalanced (txn))
1428  {
1429  const Split *osplit = xaccSplitGetOtherSplit (split);
1430 
1431  if (osplit)
1432  {
1433  gnc_commodity* split_comm =
1435  if (!gnc_commodity_equal(to_commodity, split_comm))
1436  {
1437  gchar guidstr[GUID_ENCODING_LENGTH+1];
1438  guid_to_string_buff(xaccSplitGetGUID(osplit),guidstr);
1439  PERR("The split's (%s) amount can't be converted from %s into %s.",
1440  guidstr,
1441  gnc_commodity_get_mnemonic(split_comm),
1442  gnc_commodity_get_mnemonic(to_commodity)
1443  );
1444  return gnc_numeric_zero();
1445  }
1446  return gnc_numeric_neg (xaccSplitGetAmount (osplit));
1447  }
1448  }
1449 
1450  /* ... otherwise, we need to compute the amount from the conversion
1451  * rate into _this account_. So, find the split into this account,
1452  * compute the conversion rate (based on amount/value), and then multiply
1453  * this times the split value.
1454  */
1455  value = xaccSplitGetValue (split);
1456 
1457  if (gnc_numeric_zero_p (value))
1458  {
1459  return value;
1460  }
1461 
1462  convrate = xaccTransGetAccountConvRate(txn, account);
1463  return gnc_numeric_mul (value, convrate,
1464  gnc_commodity_get_fraction (to_commodity),
1466 }
1467 
1468 /********************************************************************\
1469 \********************************************************************/
1470 
1471 gboolean
1472 xaccSplitDestroy (Split *split)
1473 {
1474  Account *acc;
1475  Transaction *trans;
1476  GncEventData ed;
1477 
1478  if (!split) return TRUE;
1479 
1480  acc = split->acc;
1481  trans = split->parent;
1482  if (acc && !qof_instance_get_destroying(acc)
1483  && !qof_instance_get_destroying(trans)
1484  && xaccTransGetReadOnly(trans))
1485  return FALSE;
1486 
1487  xaccTransBeginEdit(trans);
1488  ed.node = split;
1489  ed.idx = xaccTransGetSplitIndex(trans, split);
1490  qof_instance_set_dirty(QOF_INSTANCE(split));
1491  qof_instance_set_destroying(split, TRUE);
1492  qof_event_gen(&trans->inst, GNC_EVENT_ITEM_REMOVED, &ed);
1493  xaccTransCommitEdit(trans);
1494 
1495  return TRUE;
1496 }
1497 
1498 /********************************************************************\
1499 \********************************************************************/
1500 
1501 gint
1502 xaccSplitOrder (const Split *sa, const Split *sb)
1503 {
1504  int retval;
1505  int comp;
1506  const char *da, *db;
1507  gboolean action_for_num;
1508 
1509  if (sa == sb) return 0;
1510  /* nothing is always less than something */
1511  if (!sa) return -1;
1512  if (!sb) return +1;
1513 
1514  /* sort in transaction order, but use split action rather than trans num
1515  * according to book option */
1517  (xaccSplitGetBook (sa));
1518  if (action_for_num)
1519  retval = xaccTransOrder_num_action (sa->parent, sa->action,
1520  sb->parent, sb->action);
1521  else
1522  retval = xaccTransOrder (sa->parent, sb->parent);
1523  if (retval) return retval;
1524 
1525  /* otherwise, sort on memo strings */
1526  da = sa->memo ? sa->memo : "";
1527  db = sb->memo ? sb->memo : "";
1528  retval = g_utf8_collate (da, db);
1529  if (retval)
1530  return retval;
1531 
1532  /* otherwise, sort on action strings */
1533  da = sa->action ? sa->action : "";
1534  db = sb->action ? sb->action : "";
1535  retval = g_utf8_collate (da, db);
1536  if (retval != 0)
1537  return retval;
1538 
1539  /* the reconciled flag ... */
1540  if (sa->reconciled < sb->reconciled) return -1;
1541  if (sa->reconciled > sb->reconciled) return +1;
1542 
1543  /* compare amounts */
1545  if (comp < 0) return -1;
1546  if (comp > 0) return +1;
1547 
1549  if (comp < 0) return -1;
1550  if (comp > 0) return +1;
1551 
1552  /* if dates differ, return */
1553  if (sa->date_reconciled < sb->date_reconciled)
1554  return -1;
1555  else if (sa->date_reconciled > sb->date_reconciled)
1556  return 1;
1557 
1558  /* else, sort on guid - keeps sort stable. */
1559  retval = qof_instance_guid_compare(sa, sb);
1560  if (retval) return retval;
1561 
1562  return 0;
1563 }
1564 
1565 gint
1566 xaccSplitOrderDateOnly (const Split *sa, const Split *sb)
1567 {
1568  Transaction *ta, *tb;
1569 
1570  if (sa == sb) return 0;
1571  /* nothing is always less than something */
1572  if (!sa) return -1;
1573  if (!sb) return +1;
1574 
1575  ta = sa->parent;
1576  tb = sb->parent;
1577  if ( !ta && !tb ) return 0;
1578  if ( !tb ) return -1;
1579  if ( !ta ) return +1;
1580 
1581  if (ta->date_posted == tb->date_posted)
1582  return -1; // Keep the same order
1583  return (ta->date_posted > tb->date_posted) - (ta->date_posted < tb->date_posted);
1584 }
1585 
1586 static gboolean
1587 get_corr_account_split(const Split *sa, const Split **retval)
1588 {
1589  *retval = nullptr;
1590  g_return_val_if_fail(sa, FALSE);
1591 
1592  if (xaccTransCountSplits (sa->parent) > 2)
1593  return FALSE;
1594 
1595  *retval = xaccSplitGetOtherSplit (sa);
1596  if (*retval)
1597  return TRUE;
1598  else
1599  return FALSE;
1600 }
1601 
1602 /* TODO: these static consts can be shared. */
1603 const char *
1605 {
1606  static const char *split_const = nullptr;
1607  const Split *other_split;
1608 
1609  if (!get_corr_account_split(sa, &other_split))
1610  {
1611  if (!split_const)
1612  split_const = _("-- Split Transaction --");
1613 
1614  return split_const;
1615  }
1616 
1617  return xaccAccountGetName(other_split->acc);
1618 }
1619 
1620 char *
1622 {
1623  static const char *split_const = nullptr;
1624  const Split *other_split;
1625 
1626  if (!get_corr_account_split(sa, &other_split))
1627  {
1628  if (!split_const)
1629  split_const = _("-- Split Transaction --");
1630 
1631  return g_strdup(split_const);
1632  }
1633  return gnc_account_get_full_name(other_split->acc);
1634 }
1635 
1636 const char *
1638 {
1639  static const char *split_const = nullptr;
1640  const Split *other_split;
1641 
1642  if (!get_corr_account_split(sa, &other_split))
1643  {
1644  if (!split_const)
1645  split_const = C_("Displayed account code of the other account in a multi-split transaction", "Split");
1646 
1647  return split_const;
1648  }
1649  return xaccAccountGetCode(other_split->acc);
1650 }
1651 
1652 /* TODO: It's not too hard to make this function avoid the malloc/free. */
1653 int
1654 xaccSplitCompareAccountFullNames(const Split *sa, const Split *sb)
1655 {
1656  Account *aa, *ab;
1657  if (sa == sb) return 0;
1658  if (!sa) return -1;
1659  if (!sb) return 1;
1660 
1661  aa = sa->acc;
1662  ab = sb->acc;
1663  if (aa == ab) return 0;
1664 
1665  auto path_a = gnc_account_get_all_parents (aa);
1666  auto path_b = gnc_account_get_all_parents (ab);
1667  auto mismatch_pair = std::mismatch (path_a.rbegin(), path_a.rend(),
1668  path_b.rbegin(), path_b.rend());
1669 
1670  return mismatch_pair.first == path_a.rend() ? -1
1671  : mismatch_pair.second == path_b.rend() ? 1
1672  : g_utf8_collate (xaccAccountGetName (*mismatch_pair.first),
1673  xaccAccountGetName (*mismatch_pair.second));
1674 }
1675 
1676 
1677 int
1678 xaccSplitCompareAccountCodes(const Split *sa, const Split *sb)
1679 {
1680  Account *aa, *ab;
1681  if (!sa && !sb) return 0;
1682  if (!sa) return -1;
1683  if (!sb) return 1;
1684 
1685  aa = sa->acc;
1686  ab = sb->acc;
1687 
1688  return g_strcmp0(xaccAccountGetCode(aa), xaccAccountGetCode(ab));
1689 }
1690 
1691 int
1692 xaccSplitCompareOtherAccountFullNames(const Split *sa, const Split *sb)
1693 {
1694  char *ca, *cb;
1695  int retval;
1696  if (!sa && !sb) return 0;
1697  if (!sa) return -1;
1698  if (!sb) return 1;
1699 
1700  /* doesn't matter what separator we use
1701  * as long as they are the same
1702  */
1703 
1706  retval = g_strcmp0(ca, cb);
1707  g_free(ca);
1708  g_free(cb);
1709  return retval;
1710 }
1711 
1712 int
1713 xaccSplitCompareOtherAccountCodes(const Split *sa, const Split *sb)
1714 {
1715  const char *ca, *cb;
1716  if (!sa && !sb) return 0;
1717  if (!sa) return -1;
1718  if (!sb) return 1;
1719 
1720  ca = xaccSplitGetCorrAccountCode(sa);
1721  cb = xaccSplitGetCorrAccountCode(sb);
1722  return g_strcmp0(ca, cb);
1723 }
1724 
1725 static void
1726 qofSplitSetMemo (Split *split, const char* memo)
1727 {
1728  g_return_if_fail(split);
1729  CACHE_REPLACE(split->memo, memo);
1730 }
1731 
1732 void
1733 xaccSplitSetMemo (Split *split, const char *memo)
1734 {
1735  if (!split || !memo) return;
1736  xaccTransBeginEdit (split->parent);
1737 
1738  CACHE_REPLACE(split->memo, memo);
1739  qof_instance_set_dirty(QOF_INSTANCE(split));
1740  xaccTransCommitEdit(split->parent);
1741 
1742 }
1743 
1744 static void
1745 qofSplitSetAction (Split *split, const char *actn)
1746 {
1747  g_return_if_fail(split);
1748  CACHE_REPLACE(split->action, actn);
1749 }
1750 
1751 void
1752 xaccSplitSetAction (Split *split, const char *actn)
1753 {
1754  if (!split || !actn) return;
1755  xaccTransBeginEdit (split->parent);
1756 
1757  CACHE_REPLACE(split->action, actn);
1758  qof_instance_set_dirty(QOF_INSTANCE(split));
1759  xaccTransCommitEdit(split->parent);
1760 
1761 }
1762 
1763 static void
1764 qofSplitSetReconcile (Split *split, char recn)
1765 {
1766  g_return_if_fail(split);
1767  switch (recn)
1768  {
1769  case NREC:
1770  case CREC:
1771  case YREC:
1772  case FREC:
1773  case VREC:
1774  split->reconciled = recn;
1775  mark_split (split);
1776  xaccAccountRecomputeBalance (split->acc);
1777  break;
1778  default:
1779  PERR("Bad reconciled flag");
1780  break;
1781  }
1782 }
1783 
1784 void
1785 xaccSplitSetReconcile (Split *split, char recn)
1786 {
1787  if (!split || split->reconciled == recn) return;
1788  xaccTransBeginEdit (split->parent);
1789 
1790  switch (recn)
1791  {
1792  case NREC:
1793  case CREC:
1794  case YREC:
1795  case FREC:
1796  case VREC:
1797  split->reconciled = recn;
1798  mark_split (split);
1799  qof_instance_set_dirty(QOF_INSTANCE(split));
1800  xaccAccountRecomputeBalance (split->acc);
1801  break;
1802  default:
1803  PERR("Bad reconciled flag");
1804  break;
1805  }
1806  xaccTransCommitEdit(split->parent);
1807 
1808 }
1809 
1810 void
1812 {
1813  if (!split) return;
1814  xaccTransBeginEdit (split->parent);
1815 
1816  split->date_reconciled = secs;
1817  qof_instance_set_dirty(QOF_INSTANCE(split));
1818  xaccTransCommitEdit(split->parent);
1819 
1820 }
1821 
1822 
1823 /*################## Added for Reg2 #################*/
1824 time64
1825 xaccSplitGetDateReconciled (const Split * split)
1826 {
1827  return split ? split->date_reconciled : 0;
1828 }
1829 /*################## Added for Reg2 #################*/
1830 
1831 /********************************************************************\
1832 \********************************************************************/
1833 
1834 /* return the parent transaction of the split */
1835 Transaction *
1836 xaccSplitGetParent (const Split *split)
1837 {
1838  return split ? split->parent : nullptr;
1839 }
1840 
1841 void
1842 xaccSplitSetParent(Split *s, Transaction *t)
1843 {
1844  Transaction *old_trans;
1845  GncEventData ed;
1846 
1847  g_return_if_fail(s);
1848  if (s->parent == t) return;
1849 
1850  if (s->parent != s->orig_parent && s->orig_parent != t)
1851  PERR("You may not add the split to more than one transaction"
1852  " during the BeginEdit/CommitEdit block.");
1853  xaccTransBeginEdit(t);
1854  old_trans = s->parent;
1855 
1856  xaccTransBeginEdit(old_trans);
1857 
1858  ed.node = s;
1859  if (old_trans)
1860  {
1861  ed.idx = xaccTransGetSplitIndex(old_trans, s);
1862  qof_event_gen(&old_trans->inst, GNC_EVENT_ITEM_REMOVED, &ed);
1863  }
1864  s->parent = t;
1865 
1866  xaccTransCommitEdit(old_trans);
1867  qof_instance_set_dirty(QOF_INSTANCE(s));
1868 
1869  if (t)
1870  {
1871  /* Convert split to new transaction's commodity denominator */
1873 
1874  /* add ourselves to the new transaction's list of pending splits. */
1875  if (nullptr == g_list_find(t->splits, s))
1876  t->splits = g_list_append(t->splits, s);
1877 
1878  ed.idx = -1; /* unused */
1879  qof_event_gen(&t->inst, GNC_EVENT_ITEM_ADDED, &ed);
1880  }
1882 }
1883 
1884 
1885 GNCLot *
1886 xaccSplitGetLot (const Split *split)
1887 {
1888  return split ? split->lot : nullptr;
1889 }
1890 
1891 void
1892 xaccSplitSetLot(Split* split, GNCLot* lot)
1893 {
1894  xaccTransBeginEdit (split->parent);
1895  split->lot = lot;
1896  qof_instance_set_dirty(QOF_INSTANCE(split));
1897  xaccTransCommitEdit(split->parent);
1898 }
1899 
1900 const char *
1901 xaccSplitGetMemo (const Split *split)
1902 {
1903  return split ? split->memo : nullptr;
1904 }
1905 
1906 const char *
1907 xaccSplitGetAction (const Split *split)
1908 {
1909  return split ? split->action : nullptr;
1910 }
1911 
1912 char
1913 xaccSplitGetReconcile (const Split *split)
1914 {
1915  return split ? split->reconciled : ' ';
1916 }
1917 
1918 
1919 gnc_numeric
1920 xaccSplitGetAmount (const Split * split)
1921 {
1922  return split ? split->amount : gnc_numeric_zero();
1923 }
1924 
1925 gnc_numeric
1926 xaccSplitGetValue (const Split * split)
1927 {
1928  return split ? split->value : gnc_numeric_zero();
1929 }
1930 
1931 gnc_numeric
1932 xaccSplitGetSharePrice (const Split * split)
1933 {
1934  gnc_numeric amt, val, price;
1935  if (!split) return gnc_numeric_create(0, 1);
1936 
1937 
1938  /* if amount == 0, return 0
1939  * otherwise return value/amount
1940  */
1941 
1942  amt = xaccSplitGetAmount(split);
1943  val = xaccSplitGetValue(split);
1944  if (gnc_numeric_zero_p(amt))
1945  return gnc_numeric_create(0, 1);
1946 
1947  price = gnc_numeric_div(val, amt,
1950 
1951  /* During random checks we can get some very weird prices. Let's
1952  * handle some overflow and other error conditions by returning
1953  * zero. But still print an error to let us know it happened.
1954  */
1955  if (gnc_numeric_check(price))
1956  {
1957  PERR("Computing share price failed (%d): [ %" G_GINT64_FORMAT " / %"
1958  G_GINT64_FORMAT " ] / [ %" G_GINT64_FORMAT " / %" G_GINT64_FORMAT " ]",
1959  gnc_numeric_check(price), val.num, val.denom, amt.num, amt.denom);
1960  return gnc_numeric_create(0, 1);
1961  }
1962 
1963  return price;
1964 }
1965 
1966 /********************************************************************\
1967 \********************************************************************/
1968 
1969 QofBook *
1970 xaccSplitGetBook (const Split *split)
1971 {
1972  return qof_instance_get_book(QOF_INSTANCE(split));
1973 }
1974 
1975 const char *
1976 xaccSplitGetType(const Split *s)
1977 {
1978  if (!s) return nullptr;
1979 
1980  GValue v = G_VALUE_INIT;
1981  const char* type;
1982  qof_instance_get_kvp (QOF_INSTANCE (s), &v, 1, "split-type");
1983  type = G_VALUE_HOLDS_STRING (&v) ? g_value_get_string (&v) : nullptr;
1984  const char *rv;
1985  if (!type || !g_strcmp0 (type, split_type_normal))
1986  rv = split_type_normal;
1987  else if (!g_strcmp0 (type, split_type_stock_split))
1988  rv = split_type_stock_split;
1989  else
1990  {
1991  PERR ("unexpected split-type %s, reset to normal.", type);
1992  rv = split_type_normal;
1993  }
1994  g_value_unset (&v);
1995  return rv;
1996 }
1997 
1998 /* reconfigure a split to be a stock split - after this, you shouldn't
1999  mess with the value, just the amount. */
2000 void
2002 {
2003  GValue v = G_VALUE_INIT;
2004  xaccTransBeginEdit (s->parent);
2005 
2006  s->value = gnc_numeric_zero();
2007  g_value_init (&v, G_TYPE_STRING);
2008  g_value_set_static_string (&v, split_type_stock_split);
2009  qof_instance_set_kvp (QOF_INSTANCE (s), &v, 1, "split-type");
2010  SET_GAINS_VDIRTY(s);
2011  mark_split(s);
2012  qof_instance_set_dirty(QOF_INSTANCE(s));
2013  xaccTransCommitEdit(s->parent);
2014  g_value_unset (&v);
2015 }
2016 
2017 void
2018 xaccSplitAddPeerSplit (Split *split, const Split *other_split,
2019  time64 timestamp)
2020 {
2021  const GncGUID* guid;
2022 
2023  g_return_if_fail (split != nullptr);
2024  g_return_if_fail (other_split != nullptr);
2025 
2026  guid = qof_instance_get_guid (QOF_INSTANCE (other_split));
2027  xaccTransBeginEdit (split->parent);
2028  qof_instance_kvp_add_guid (QOF_INSTANCE (split), "lot-split",
2029  gnc_time(nullptr), "peer_guid", guid_copy(guid));
2030  mark_split (split);
2031  qof_instance_set_dirty (QOF_INSTANCE (split));
2032  xaccTransCommitEdit (split->parent);
2033 }
2034 
2035 gboolean
2036 xaccSplitHasPeers (const Split *split)
2037 {
2038  return qof_instance_has_slot (QOF_INSTANCE (split), "lot-split");
2039 }
2040 
2041 gboolean
2042 xaccSplitIsPeerSplit (const Split *split, const Split *other_split)
2043 {
2044  const GncGUID* guid;
2045 
2046  g_return_val_if_fail (split != nullptr, FALSE);
2047  g_return_val_if_fail (other_split != nullptr, FALSE);
2048 
2049  guid = qof_instance_get_guid (QOF_INSTANCE (other_split));
2050  return qof_instance_kvp_has_guid (QOF_INSTANCE (split), "lot-split",
2051  "peer_guid", guid);
2052 }
2053 
2054 void
2055 xaccSplitRemovePeerSplit (Split *split, const Split *other_split)
2056 {
2057  const GncGUID* guid;
2058 
2059  g_return_if_fail (split != nullptr);
2060  g_return_if_fail (other_split != nullptr);
2061 
2062  guid = qof_instance_get_guid (QOF_INSTANCE (other_split));
2063  xaccTransBeginEdit (split->parent);
2064  qof_instance_kvp_remove_guid (QOF_INSTANCE (split), "lot-split",
2065  "peer_guid", guid);
2066  mark_split (split);
2067  qof_instance_set_dirty (QOF_INSTANCE (split));
2068  xaccTransCommitEdit (split->parent);
2069 }
2070 
2071 void
2072 xaccSplitMergePeerSplits (Split *split, const Split *other_split)
2073 {
2074  xaccTransBeginEdit (split->parent);
2075  qof_instance_kvp_merge_guids (QOF_INSTANCE (split),
2076  QOF_INSTANCE (other_split), "lot-split");
2077  mark_split (split);
2078  qof_instance_set_dirty (QOF_INSTANCE (split));
2079  xaccTransCommitEdit (split->parent);
2080 }
2081 
2082 /********************************************************************\
2083 \********************************************************************/
2084 /* In the old world, the 'other split' was the other split of a
2085  * transaction that contained only two splits. In the new world,
2086  * a split may have been cut up between multiple lots, although
2087  * in a conceptual sense, if lots hadn't been used, there would be
2088  * only a pair. So we handle this conceptual case: we can still
2089  * identify, unambiguously, the 'other' split when 'this' split
2090  * as been cut up across lots. We do this by looking for the
2091  * 'lot-split' keyword, which occurs only in cut-up splits.
2092  */
2093 
2094 Split *
2095 xaccSplitGetOtherSplit (const Split *split)
2096 {
2097  Transaction *trans;
2098  Split *other = nullptr;
2099 
2100  if (!split) return nullptr;
2101  trans = split->parent;
2102  if (!trans) return nullptr;
2103 
2104  for (GList *n = xaccTransGetSplitList (trans); n; n = n->next)
2105  {
2106  Split *s = GNC_SPLIT(n->data);
2107  if ((s == split) ||
2108  (!xaccTransStillHasSplit(trans, s)) ||
2110  (qof_instance_has_slot (QOF_INSTANCE (s), "lot-split")))
2111  continue;
2112 
2113  if (other)
2114  return nullptr;
2115 
2116  other = s;
2117  }
2118  return other;
2119 }
2120 
2121 /********************************************************************\
2122 \********************************************************************/
2123 
2124 gnc_numeric
2125 xaccSplitVoidFormerAmount(const Split *split)
2126 {
2127  GValue v = G_VALUE_INIT;
2128  gnc_numeric *num = nullptr;
2129  gnc_numeric retval;
2130  g_return_val_if_fail(split, gnc_numeric_zero());
2131  qof_instance_get_kvp (QOF_INSTANCE (split), &v, 1, void_former_amt_str);
2132  if (G_VALUE_HOLDS_BOXED (&v))
2133  num = (gnc_numeric*)g_value_get_boxed (&v);
2134  retval = num ? *num : gnc_numeric_zero();
2135  g_value_unset (&v);
2136  return retval;
2137 }
2138 
2139 gnc_numeric
2140 xaccSplitVoidFormerValue(const Split *split)
2141 {
2142  GValue v = G_VALUE_INIT;
2143  gnc_numeric *num = nullptr;
2144  gnc_numeric retval;
2145  g_return_val_if_fail(split, gnc_numeric_zero());
2146  qof_instance_get_kvp (QOF_INSTANCE (split), &v, 1, void_former_val_str);
2147  if (G_VALUE_HOLDS_BOXED (&v))
2148  num = (gnc_numeric*)g_value_get_boxed (&v);
2149  retval = num ? *num : gnc_numeric_zero();
2150  g_value_unset (&v);
2151  return retval;
2152 }
2153 
2154 void
2155 xaccSplitVoid(Split *split)
2156 {
2157  gnc_numeric zero = gnc_numeric_zero(), num;
2158  GValue v = G_VALUE_INIT;
2159 
2160  g_value_init (&v, GNC_TYPE_NUMERIC);
2161  num = xaccSplitGetAmount(split);
2162  g_value_set_boxed (&v, &num);
2163  qof_instance_set_kvp (QOF_INSTANCE (split), &v, 1, void_former_amt_str);
2164  g_value_reset (&v);
2165  num = xaccSplitGetValue(split);
2166  g_value_set_boxed (&v, &num);
2167  qof_instance_set_kvp (QOF_INSTANCE (split), &v, 1, void_former_val_str);
2168 
2169  /* Marking dirty handled by SetAmount etc. */
2170  xaccSplitSetAmount (split, zero);
2171  xaccSplitSetValue (split, zero);
2172  xaccSplitSetReconcile(split, VREC);
2173  g_value_unset (&v);
2174 }
2175 
2176 void
2177 xaccSplitUnvoid(Split *split)
2178 {
2181  xaccSplitSetReconcile(split, NREC);
2182  qof_instance_set_kvp (QOF_INSTANCE (split), nullptr, 1, void_former_amt_str);
2183  qof_instance_set_kvp (QOF_INSTANCE (split), nullptr, 1, void_former_val_str);
2184  qof_instance_set_dirty (QOF_INSTANCE (split));
2185 }
2186 
2187 /********************************************************************\
2188 \********************************************************************/
2189 /* QofObject function implementation */
2190 
2191 /* Hook into the QofObject registry */
2192 
2193 #ifdef _MSC_VER
2194 /* MSVC compiler doesn't have C99 "designated initializers"
2195  * so we wrap them in a macro that is empty on MSVC. */
2196 # define DI(x) /* */
2197 #else
2198 # define DI(x) x
2199 #endif
2200 static QofObject split_object_def =
2201 {
2202  DI(.interface_version = ) QOF_OBJECT_VERSION,
2203  DI(.e_type = ) GNC_ID_SPLIT,
2204  DI(.type_label = ) "Split",
2205  DI(.create = ) (void* (*)(QofBook*))xaccMallocSplit,
2206  DI(.book_begin = ) nullptr,
2207  DI(.book_end = ) nullptr,
2208  DI(.is_dirty = ) qof_collection_is_dirty,
2209  DI(.mark_clean = ) qof_collection_mark_clean,
2210  DI(.foreach = ) qof_collection_foreach,
2211  DI(.printable = ) (const char * (*)(gpointer)) xaccSplitGetMemo,
2212  DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
2213 };
2214 
2215 static gpointer
2216 split_account_guid_getter (gpointer obj, const QofParam *p)
2217 {
2218  Split *s = GNC_SPLIT(obj);
2219  Account *acc;
2220 
2221  if (!s) return nullptr;
2222  acc = xaccSplitGetAccount (s);
2223  if (!acc) return nullptr;
2224  return ((gpointer)xaccAccountGetGUID (acc));
2225 }
2226 
2227 static double /* internal use only */
2228 DxaccSplitGetShareAmount (const Split * split)
2229 {
2230  return split ? gnc_numeric_to_double(xaccSplitGetAmount(split)) : 0.0;
2231 }
2232 
2233 static gpointer
2234 no_op (gpointer obj, const QofParam *p)
2235 {
2236  return obj;
2237 }
2238 
2239 static void
2240 qofSplitSetParentTrans(Split *s, QofInstance *ent)
2241 {
2242  Transaction *trans = (Transaction*)ent;
2243 
2244  g_return_if_fail(trans);
2245  xaccSplitSetParent(s, trans);
2246 }
2247 
2248 static void
2249 qofSplitSetAccount(Split *s, QofInstance *ent)
2250 {
2251  Account *acc = (Account*)ent;
2252 
2253  g_return_if_fail(acc);
2254  xaccSplitSetAccount(s, acc);
2255 }
2256 
2257 gboolean xaccSplitRegister (void)
2258 {
2259  static const QofParam params[] =
2260  {
2261  {
2262  SPLIT_DATE_RECONCILED, QOF_TYPE_DATE,
2265  },
2266 
2267  /* d-* are deprecated query params, should not be used in new
2268  * queries, should be removed from old queries. */
2269  {
2270  "d-share-amount", QOF_TYPE_DOUBLE,
2271  (QofAccessFunc)DxaccSplitGetShareAmount, nullptr
2272  },
2273  {
2274  "d-share-int64", QOF_TYPE_INT64,
2276  },
2277  {
2278  SPLIT_BALANCE, QOF_TYPE_NUMERIC,
2280  },
2281  {
2282  SPLIT_CLEARED_BALANCE, QOF_TYPE_NUMERIC,
2284  },
2285  {
2286  SPLIT_RECONCILED_BALANCE, QOF_TYPE_NUMERIC,
2288  },
2289  {
2290  SPLIT_MEMO, QOF_TYPE_STRING,
2291  (QofAccessFunc)xaccSplitGetMemo, (QofSetterFunc)qofSplitSetMemo
2292  },
2293  {
2294  SPLIT_ACTION, QOF_TYPE_STRING,
2295  (QofAccessFunc)xaccSplitGetAction, (QofSetterFunc)qofSplitSetAction
2296  },
2297  {
2298  SPLIT_RECONCILE, QOF_TYPE_CHAR,
2300  (QofSetterFunc)qofSplitSetReconcile
2301  },
2302  {
2303  SPLIT_AMOUNT, QOF_TYPE_NUMERIC,
2304  (QofAccessFunc)xaccSplitGetAmount, (QofSetterFunc)qofSplitSetAmount
2305  },
2306  {
2307  SPLIT_SHARE_PRICE, QOF_TYPE_NUMERIC,
2309  (QofSetterFunc)qofSplitSetSharePrice
2310  },
2311  {
2312  SPLIT_VALUE, QOF_TYPE_DEBCRED,
2313  (QofAccessFunc)xaccSplitGetValue, (QofSetterFunc)qofSplitSetValue
2314  },
2315  { SPLIT_TYPE, QOF_TYPE_STRING, (QofAccessFunc)xaccSplitGetType, nullptr },
2316  {
2317  SPLIT_VOIDED_AMOUNT, QOF_TYPE_NUMERIC,
2319  },
2320  {
2321  SPLIT_VOIDED_VALUE, QOF_TYPE_NUMERIC,
2323  },
2324  { SPLIT_LOT, GNC_ID_LOT, (QofAccessFunc)xaccSplitGetLot, nullptr },
2325  {
2326  SPLIT_TRANS, GNC_ID_TRANS,
2328  (QofSetterFunc)qofSplitSetParentTrans
2329  },
2330  {
2331  SPLIT_ACCOUNT, GNC_ID_ACCOUNT,
2332  (QofAccessFunc)xaccSplitGetAccount, (QofSetterFunc)qofSplitSetAccount
2333  },
2334  { SPLIT_ACCOUNT_GUID, QOF_TYPE_GUID, split_account_guid_getter, nullptr },
2335  /* these are no-ops to register the parameter names (for sorting) but
2336  they return an allocated object which getters cannot do. */
2337  { SPLIT_ACCT_FULLNAME, SPLIT_ACCT_FULLNAME, no_op, nullptr },
2338  { SPLIT_CORR_ACCT_NAME, SPLIT_CORR_ACCT_NAME, no_op, nullptr },
2339  { SPLIT_CORR_ACCT_CODE, SPLIT_CORR_ACCT_CODE, no_op, nullptr },
2340  { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)xaccSplitGetBook, nullptr },
2341  {
2342  QOF_PARAM_GUID, QOF_TYPE_GUID,
2344  },
2345  { nullptr },
2346  };
2347 
2348  qof_class_register (GNC_ID_SPLIT, (QofSortFunc)xaccSplitOrder, params);
2349  qof_class_register (SPLIT_ACCT_FULLNAME,
2351  qof_class_register (SPLIT_CORR_ACCT_NAME,
2353  nullptr);
2354  qof_class_register (SPLIT_CORR_ACCT_CODE,
2356 
2357  return qof_object_register (&split_object_def);
2358 }
2359 
2361 _utest_split_fill_functions (void)
2362 {
2363  SplitTestFunctions *func = g_new (SplitTestFunctions, 1);
2364 
2365  func->xaccSplitEqualCheckBal = xaccSplitEqualCheckBal;
2366  func->get_currency_denom = get_currency_denom;
2367  func->get_commodity_denom = get_commodity_denom;
2368  func->get_corr_account_split = get_corr_account_split;
2369  return func;
2370 }
2371 
2372 /************************ END OF ************************************\
2373 \************************* FILE *************************************/
void xaccSplitSetValue(Split *s, gnc_numeric amt)
The xaccSplitSetValue() method sets the value of this split in the transaction&#39;s commodity.
Definition: Split.cpp:1261
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
Compare two instances, based on their last update times.
gnc_numeric xaccSplitGetClearedBalance(const Split *s)
The cleared-balance is the currency-denominated balance of all transactions that have been marked as ...
Definition: Split.cpp:1309
gint xaccSplitOrder(const Split *sa, const Split *sb)
The xaccSplitOrder(sa,sb) method is useful for sorting.
Definition: Split.cpp:1502
This is the private header for the account structure.
void xaccSplitAddPeerSplit(Split *split, const Split *other_split, time64 timestamp)
Add a peer split to this split&#39;s lot-split list.
Definition: Split.cpp:2018
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b represent the same number.
void xaccSplitSetBaseValue(Split *s, gnc_numeric value, const gnc_commodity *base_currency)
Depending on the base_currency, set either the value or the amount of this split or both: If the base...
Definition: Split.cpp:1321
void xaccSplitSetAction(Split *split, const char *actn)
The Action is an arbitrary user-assigned string.
Definition: Split.cpp:1752
gchar * gnc_num_dbg_to_string(gnc_numeric n)
Convert to string.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
void xaccSplitMakeStockSplit(Split *s)
Mark a split to be of type stock split - after this, you shouldn&#39;t modify the value anymore...
Definition: Split.cpp:2001
const GncGUID * qof_instance_get_guid(gconstpointer inst)
Return the GncGUID of this instance.
void qof_instance_set_kvp(QofInstance *, GValue const *value, unsigned count,...)
Sets a KVP slot to a value from a GValue.
int xaccSplitCompareAccountCodes(const Split *sa, const Split *sb)
Compare two splits by code of account.
Definition: Split.cpp:1678
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
#define qof_instance_is_dirty
Return value of is_dirty flag.
Definition: qofinstance.h:166
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
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
gnc_numeric xaccSplitGetReconciledBalance(const Split *s)
Returns the reconciled-balance of this split.
Definition: Split.cpp:1315
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account&#39;s account type.
Definition: Account.cpp:3217
gboolean xaccSplitDestroy(Split *split)
Destructor.
Definition: Split.cpp:1472
QofBackendError
The errors that can be reported to the GUI & other front-end users.
Definition: qofbackend.h:57
int xaccAccountGetCommoditySCU(const Account *acc)
Return the SCU for the account.
Definition: Account.cpp:2696
const char * xaccAccountGetCode(const Account *acc)
Get the account&#39;s accounting code.
Definition: Account.cpp:3286
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value...
STRUCTS.
GncGUID * guid_copy(const GncGUID *guid)
Returns a newly allocated GncGUID that matches the passed-in GUID.
Definition: guid.cpp:120
const char * xaccTransGetReadOnly(Transaction *trans)
Returns a non-NULL value if this Transaction was marked as read-only with some specific "reason" text...
gboolean qof_instance_get_destroying(gconstpointer ptr)
Retrieve the flag that indicates whether or not this object is about to be destroyed.
void xaccSplitCopyOnto(const Split *from_split, Split *to_split)
This is really a helper for xaccTransCopyOnto.
Definition: Split.cpp:639
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.
gboolean qof_book_use_split_action_for_num_field(const QofBook *book)
Returns TRUE if this book uses split action field as the &#39;Num&#39; field, FALSE if it uses transaction nu...
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
char xaccSplitGetReconcile(const Split *split)
Returns the value of the reconcile flag.
Definition: Split.cpp:1913
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equal.
void gnc_lot_add_split(GNCLot *lot, Split *split)
Adds a split to this lot.
Definition: gnc-lot.cpp:594
gboolean gnc_account_remove_split(Account *acc, Split *s)
Remove the given split from an account.
Definition: Account.cpp:1955
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
Object instance holds common fields that most gnucash objects use.
void xaccSplitSetReconcile(Split *split, char recn)
Set the reconcile flag.
Definition: Split.cpp:1785
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.
Definition: Split.cpp:1836
API for Transactions and Splits (journal entries)
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
Definition: guid.cpp:173
void xaccSplitRemovePeerSplit(Split *split, const Split *other_split)
Remove a peer split from this split&#39;s lot-split list.
Definition: Split.cpp:2055
int(* QofSortFunc)(gconstpointer, gconstpointer)
This function is the default sort function for a particular object type.
Definition: qofclass.h:223
int gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
Returns 1 if a>b, -1 if b>a, 0 if a == b.
gboolean xaccTransIsBalanced(const Transaction *trans)
Returns true if the transaction is balanced according to the rules currently in effect.
#define QOF_OBJECT_VERSION
Defines the version of the core object object registration interface.
Definition: qofobject.h:63
gchar * gnc_numeric_to_string(gnc_numeric n)
Convert to string.
int xaccSplitCompareOtherAccountFullNames(const Split *sa, const Split *sb)
Compare two splits by full name of the other account.
Definition: Split.cpp:1692
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
QofBook * xaccSplitGetBook(const Split *split)
Returns the book of this split, i.e.
Definition: Split.cpp:1970
int xaccTransOrder_num_action(const Transaction *ta, const char *actna, const Transaction *tb, const char *actnb)
The xaccTransOrder_num_action(ta,actna,tb,actnb) method is useful for sorting.
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
gnc_numeric xaccSplitGetBalance(const Split *s)
Returns the running balance up to and including the indicated split.
Definition: Split.cpp:1297
#define QOF_PARAM_BOOK
"Known" Object Parameters – all objects must support these
Definition: qofquery.h:108
Split * xaccSplitGetCapGainsSplit(const Split *split)
The xaccSplitGetCapGainsSplit() routine returns the split that records the cap gains for this split...
Definition: cap-gains.cpp:480
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.
int xaccSplitCompareAccountFullNames(const Split *sa, const Split *sb)
Compare two splits by full name of account.
Definition: Split.cpp:1654
#define VREC
split is void
Definition: Split.h:77
Account used to record multiple commodity transactions.
Definition: Account.h:155
gboolean xaccSplitEqual(const Split *sa, const Split *sb, gboolean check_guids, gboolean check_balances, gboolean check_txn_splits)
Equality.
Definition: Split.cpp:802
gboolean xaccSplitHasPeers(const Split *split)
Does this split have peers?
Definition: Split.cpp:2036
void qof_instance_init_data(QofInstance *inst, QofIdType type, QofBook *book)
Initialise the settings associated with an instance.
int xaccTransCountSplits(const Transaction *trans)
Returns the number of splits in this transaction.
#define xaccAccountGetGUID(X)
Definition: Account.h:248
double gnc_numeric_to_double(gnc_numeric in)
Convert numeric to floating-point value.
convert single-entry accounts to clean double-entry
void xaccSplitMergePeerSplits(Split *split, const Split *other_split)
Merge the other_split&#39;s peer splits into split&#39;s peers.
Definition: Split.cpp:2072
gnc_numeric xaccSplitVoidFormerAmount(const Split *split)
Returns the original pre-void amount of a split.
Definition: Split.cpp:2125
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
The xaccSplitLookup() subroutine will return the split associated with the given id, or NULL if there is no such split.
Definition: Split.cpp:1071
guint32 qof_instance_get_idata(gconstpointer inst)
get the instance tag number used for kvp management in sql backends.
void xaccSplitSetAmount(Split *s, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account&#39;s commodity that the split should have...
Definition: Split.cpp:1225
gchar * gnc_account_get_full_name(const Account *account)
The gnc_account_get_full_name routine returns the fully qualified name of the account using the given...
Definition: Account.cpp:3255
gboolean xaccTransEqual(const Transaction *ta, const Transaction *tb, gboolean check_guids, gboolean check_splits, gboolean check_balances, gboolean assume_ordered)
Equality.
gnc_numeric gnc_numeric_convert(gnc_numeric n, gint64 denom, gint how)
Change the denominator of a gnc_numeric value to the specified denominator under standard arguments &#39;...
gnc_numeric xaccSplitVoidFormerValue(const Split *split)
Returns the original pre-void value of a split.
Definition: Split.cpp:2140
Account public routines (C++ api)
#define YREC
The Split has been reconciled.
Definition: Split.h:74
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Multiply a times b, returning the product.
const char * gnc_numeric_errorCode_to_string(GNCNumericErrorCode error_code)
Returns a string representation of the given GNCNumericErrorCode.
void xaccSplitSetMemo(Split *split, const char *memo)
The memo is an arbitrary string associated with a split.
Definition: Split.cpp:1733
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
Definition: guid.h:84
#define FREC
frozen into accounting period
Definition: Split.h:75
int xaccSplitCompareOtherAccountCodes(const Split *sa, const Split *sb)
Compare two splits by code of the other account.
Definition: Split.cpp:1713
void xaccSplitSetSharePriceAndAmount(Split *s, gnc_numeric price, gnc_numeric amt)
The xaccSplitSetSharePriceAndAmount() method will simultaneously update the share price and the numbe...
Definition: Split.cpp:1159
void qof_instance_copy_book(gpointer ptr1, gconstpointer ptr2)
Copy the book from one QofInstances to another.
gnc_numeric xaccSplitGetNoclosingBalance(const Split *s)
The noclosing-balance is the currency-denominated balance of all transactions except &#39;closing&#39; transa...
Definition: Split.cpp:1303
#define SPLIT_ACCOUNT_GUID
for guid_match_all
Definition: Split.h:544
void xaccAccountRecomputeBalance(Account *acc)
The following recompute the partial balances (stored with the transaction) and the total balance...
Definition: Account.cpp:2261
gboolean xaccSplitIsPeerSplit(const Split *split, const Split *other_split)
Report if a split is a peer of this one.
Definition: Split.cpp:2042
char * xaccSplitGetCorrAccountFullName(const Split *sa)
These functions take a split, get the corresponding split on the "other side" of the transaction...
Definition: Split.cpp:1621
void gnc_lot_remove_split(GNCLot *lot, Split *split)
Adds a split from this lot.
Definition: gnc-lot.cpp:646
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
#define MAX_DATE_LENGTH
The maximum length of a string created by the date printers.
Definition: gnc-date.h:108
void qof_collection_mark_clean(QofCollection *)
reset value of dirty flag
Definition: qofid.cpp:261
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
Additional event handling code.
gnc_numeric gnc_numeric_div(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Division.
#define xaccSplitGetGUID(X)
Definition: Split.h:552
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
gnc_numeric xaccSplitGetSharePrice(const Split *split)
Returns the price of the split, that is, the value divided by the amount.
Definition: Split.cpp:1932
int xaccTransGetSplitIndex(const Transaction *trans, const Split *split)
Inverse of xaccTransGetSplit()
gboolean gnc_numeric_eq(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b are exactly the same (have the same numerator and ...
All type declarations for the whole Gnucash engine.
const GncGUID * qof_entity_get_guid(gconstpointer ent)
#define CREC
The Split has been cleared.
Definition: Split.h:73
gboolean qof_instance_books_equal(gconstpointer ptr1, gconstpointer ptr2)
See if two QofInstances share the same book.
gnc_numeric xaccSplitGetBaseValue(const Split *s, const gnc_commodity *base_currency)
Depending on the base_currency, return either the value or the amount of this split: If the base_curr...
Definition: Split.cpp:1376
Split * xaccMallocSplit(QofBook *book)
Constructor.
Definition: Split.cpp:532
const char * xaccSplitGetCorrAccountName(const Split *sa)
document me
Definition: Split.cpp:1604
Encapsulate all the information about a dataset.
gboolean gnc_account_insert_split(Account *acc, Split *s)
Insert the given split from an account.
Definition: Account.cpp:1925
void xaccSplitSetLot(Split *split, GNCLot *lot)
Assigns the split to a specific Lot.
Definition: Split.cpp:1892
API for the transaction logger.
const char * gnc_commodity_get_printname(const gnc_commodity *cm)
Retrieve the &#39;print&#39; name for the specified commodity.
void xaccSplitSetDateReconciledSecs(Split *split, time64 secs)
Set the date on which this split was reconciled by specifying the time as time64. ...
Definition: Split.cpp:1811
time64 xaccSplitGetDateReconciled(const Split *split)
Retrieve the date when the Split was reconciled.
Definition: Split.cpp:1825
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction&#39;s commodity.
Definition: Split.cpp:1926
Account * xaccSplitGetAccount(const Split *s)
Returns the account of this split, which was set through xaccAccountInsertSplit().
Definition: Split.cpp:936
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account&#39;s commodity.
Definition: Account.cpp:3351
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Returns the valuation commodity of this transaction.
#define xaccAccountInsertSplit(acc, s)
The xaccAccountInsertSplit() method will insert the indicated split into the indicated account...
Definition: Account.h:1048
gint qof_instance_guid_compare(gconstpointer ptr1, gconstpointer ptr2)
Compare the GncGUID values of two instances.
const char * xaccSplitGetCorrAccountCode(const Split *sa)
document me
Definition: Split.cpp:1637
Split * xaccSplitGetOtherSplit(const Split *split)
The xaccSplitGetOtherSplit() is a convenience routine that returns the other of a pair of splits...
Definition: Split.cpp:2095
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
Definition: gnc-numeric.h:165
void xaccSplitSetSharePrice(Split *s, gnc_numeric price)
Definition: Split.cpp:1187
time64 gnc_time(time64 *tbuf)
get the current time
Definition: gnc-date.cpp:261
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.
const char * xaccSplitGetMemo(const Split *split)
Returns the memo string.
Definition: Split.cpp:1901
const char * xaccSplitGetAction(const Split *split)
Returns the action string.
Definition: Split.cpp:1907
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
Definition: qofbook.cpp:521
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
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 * xaccSplitGetType(const Split *s)
The xaccIsPeerSplit() is a convenience routine that returns TRUE (a non-zero value) if the two splits...
Definition: Split.cpp:1976
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
#define GNC_EVENT_ITEM_ADDED
These events are used when a split is added to an account.
Definition: gnc-event.h:45
No error.
Definition: gnc-numeric.h:223
#define GNC_DENOM_AUTO
Values that can be passed as the &#39;denom&#39; argument.
Definition: gnc-numeric.h:245
The type used to store guids in C.
Definition: guid.h:75
Utilities to Automatically Compute Capital Gains/Losses.
size_t qof_print_date_buff(char *buff, size_t buflen, time64 secs)
Convenience: calls through to qof_print_date_dmy_buff().
Definition: gnc-date.cpp:573
SplitList * xaccTransGetSplitList(const Transaction *trans)
The xaccTransGetSplitList() method returns a GList of the splits in a transaction.
Commodity handling public routines.
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equivalent.
GNCLot * xaccSplitGetLot(const Split *split)
Returns the pointer to the debited/credited Lot where this split belongs to, or NULL if it doesn&#39;t be...
Definition: Split.cpp:1886
#define NREC
not reconciled or cleared
Definition: Split.h:76
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account&#39;s commodity.
Definition: Split.cpp:1920