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