GnuCash  5.6-150-g038405b370+
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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  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  if (auto v = qof_instance_get_path_kvp<GncGUID*> (QOF_INSTANCE (split), {"gains-source"}))
1106  guid = const_cast<GncGUID*>(*v);
1107 
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 }
1123 
1124 /********************************************************************\
1125 \********************************************************************/
1126 
1127 static inline int
1128 get_currency_denom(const Split * s)
1129 {
1130  if (!(s && s->parent && s->parent->common_currency))
1131  {
1132  return GNC_DENOM_AUTO;
1133  }
1134  else
1135  {
1136  return gnc_commodity_get_fraction (s->parent->common_currency);
1137  }
1138 }
1139 
1140 static inline int
1141 get_commodity_denom(const Split * s)
1142 {
1143  if (!(s && s->acc))
1144  {
1145  return GNC_DENOM_AUTO;
1146  }
1147  else
1148  {
1149  return xaccAccountGetCommoditySCU(s->acc);
1150  }
1151 }
1152 
1153 /********************************************************************\
1154 \********************************************************************/
1155 
1156 void
1157 xaccSplitSetSharePriceAndAmount (Split *s, gnc_numeric price, gnc_numeric amt)
1158 {
1159  if (!s) return;
1160  ENTER (" ");
1161  xaccTransBeginEdit (s->parent);
1162 
1163  s->amount = gnc_numeric_convert(amt, get_commodity_denom(s),
1165  s->value = gnc_numeric_mul(s->amount, price,
1166  get_currency_denom(s), GNC_HOW_RND_ROUND_HALF_UP);
1167 
1168  SET_GAINS_A_VDIRTY(s);
1169  mark_split (s);
1170  qof_instance_set_dirty(QOF_INSTANCE(s));
1171  xaccTransCommitEdit(s->parent);
1172  LEAVE ("");
1173 }
1174 
1175 static void
1176 qofSplitSetSharePrice (Split *split, gnc_numeric price)
1177 {
1178  g_return_if_fail(split);
1179  split->value = gnc_numeric_mul(xaccSplitGetAmount(split),
1180  price, get_currency_denom(split),
1182 }
1183 
1184 void
1185 xaccSplitSetSharePrice (Split *s, gnc_numeric price)
1186 {
1187  if (!s) return;
1188 
1189  if (gnc_numeric_zero_p (price))
1190  return;
1191 
1192  ENTER (" ");
1193  xaccTransBeginEdit (s->parent);
1194 
1195  s->value = gnc_numeric_mul(xaccSplitGetAmount(s),
1196  price, get_currency_denom(s),
1198 
1199  SET_GAINS_VDIRTY(s);
1200  mark_split (s);
1201  qof_instance_set_dirty(QOF_INSTANCE(s));
1202  xaccTransCommitEdit(s->parent);
1203  LEAVE ("");
1204 }
1205 
1206 static void
1207 qofSplitSetAmount (Split *split, gnc_numeric amt)
1208 {
1209  g_return_if_fail(split);
1210  if (split->acc)
1211  {
1212  split->amount = gnc_numeric_convert(amt,
1213  get_commodity_denom(split), GNC_HOW_RND_ROUND_HALF_UP);
1214  }
1215  else
1216  {
1217  split->amount = amt;
1218  }
1219 }
1220 
1221 /* The amount of the split in the _account's_ commodity. */
1222 void
1223 xaccSplitSetAmount (Split *s, gnc_numeric amt)
1224 {
1225  if (!s) return;
1226  g_return_if_fail(gnc_numeric_check(amt) == GNC_ERROR_OK);
1227  ENTER ("(split=%p) old amt=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT
1228  " new amt=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, s,
1229  s->amount.num, s->amount.denom, amt.num, amt.denom);
1230 
1231  xaccTransBeginEdit (s->parent);
1232  if (s->acc)
1233  {
1234  s->amount = gnc_numeric_convert(amt, get_commodity_denom(s),
1236  g_assert (gnc_numeric_check (s->amount) == GNC_ERROR_OK);
1237  }
1238  else
1239  s->amount = amt;
1240 
1241  SET_GAINS_ADIRTY(s);
1242  mark_split (s);
1243  qof_instance_set_dirty(QOF_INSTANCE(s));
1244  xaccTransCommitEdit(s->parent);
1245  LEAVE("");
1246 }
1247 
1248 static void
1249 qofSplitSetValue (Split *split, gnc_numeric amt)
1250 {
1251  g_return_if_fail(split);
1252  split->value = gnc_numeric_convert(amt,
1253  get_currency_denom(split), GNC_HOW_RND_ROUND_HALF_UP);
1254  g_assert(gnc_numeric_check (split->value) != GNC_ERROR_OK);
1255 }
1256 
1257 /* The value of the split in the _transaction's_ currency. */
1258 void
1259 xaccSplitSetValue (Split *s, gnc_numeric amt)
1260 {
1261  gnc_numeric new_val;
1262  if (!s) return;
1263 
1264  g_return_if_fail(gnc_numeric_check(amt) == GNC_ERROR_OK);
1265  ENTER ("(split=%p) old val=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT
1266  " new val=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, s,
1267  s->value.num, s->value.denom, amt.num, amt.denom);
1268 
1269  xaccTransBeginEdit (s->parent);
1270  new_val = gnc_numeric_convert(amt, get_currency_denom(s),
1272  if (gnc_numeric_check(new_val) == GNC_ERROR_OK &&
1273  !(gnc_numeric_zero_p (new_val) && !gnc_numeric_zero_p (amt)))
1274  {
1275  s->value = new_val;
1276  }
1277  else
1278  {
1279  PERR("numeric error %s in converting the split value's denominator with amount %s and denom %d",
1281  gnc_num_dbg_to_string (amt), get_currency_denom(s));
1282  }
1283 
1284  SET_GAINS_VDIRTY(s);
1285  mark_split (s);
1286  qof_instance_set_dirty(QOF_INSTANCE(s));
1287  xaccTransCommitEdit(s->parent);
1288  LEAVE ("");
1289 }
1290 
1291 /********************************************************************\
1292 \********************************************************************/
1293 
1294 gnc_numeric
1295 xaccSplitGetBalance (const Split *s)
1296 {
1297  return s ? s->balance : gnc_numeric_zero();
1298 }
1299 
1300 gnc_numeric
1302 {
1303  return s ? s->noclosing_balance : gnc_numeric_zero();
1304 }
1305 
1306 gnc_numeric
1308 {
1309  return s ? s->cleared_balance : gnc_numeric_zero();
1310 }
1311 
1312 gnc_numeric
1314 {
1315  return s ? s->reconciled_balance : gnc_numeric_zero();
1316 }
1317 
1318 void
1319 xaccSplitSetBaseValue (Split *s, gnc_numeric value,
1320  const gnc_commodity * base_currency)
1321 {
1322  const gnc_commodity *currency;
1323  const gnc_commodity *commodity;
1324 
1325  if (!s) return;
1326  xaccTransBeginEdit (s->parent);
1327 
1328  if (!s->acc)
1329  {
1330  PERR ("split must have a parent account");
1331  return;
1332  }
1333 
1334  currency = xaccTransGetCurrency (s->parent);
1335  commodity = xaccAccountGetCommodity (s->acc);
1336 
1337  /* If the base_currency is the transaction's commodity ('currency'),
1338  * set the value. If it's the account commodity, set the
1339  * amount. If both, set both. */
1340  if (gnc_commodity_equiv(currency, base_currency))
1341  {
1342  if (gnc_commodity_equiv(commodity, base_currency))
1343  {
1344  s->amount = gnc_numeric_convert(value,
1345  get_commodity_denom(s),
1347  }
1348  s->value = gnc_numeric_convert(value,
1349  get_currency_denom(s),
1351  }
1352  else if (gnc_commodity_equiv(commodity, base_currency))
1353  {
1354  s->amount = gnc_numeric_convert(value, get_commodity_denom(s),
1356  }
1357  else
1358  {
1359  PERR ("inappropriate base currency %s "
1360  "given split currency=%s and commodity=%s\n",
1361  gnc_commodity_get_printname(base_currency),
1362  gnc_commodity_get_printname(currency),
1363  gnc_commodity_get_printname(commodity));
1364  return;
1365  }
1366 
1367  SET_GAINS_A_VDIRTY(s);
1368  mark_split (s);
1369  qof_instance_set_dirty(QOF_INSTANCE(s));
1370  xaccTransCommitEdit(s->parent);
1371 }
1372 
1373 gnc_numeric
1374 xaccSplitGetBaseValue (const Split *s, const gnc_commodity * base_currency)
1375 {
1376  if (!s || !s->acc || !s->parent) return gnc_numeric_zero();
1377 
1378  /* be more precise -- the value depends on the currency we want it
1379  * expressed in. */
1380  if (gnc_commodity_equiv(xaccTransGetCurrency(s->parent), base_currency))
1381  return xaccSplitGetValue(s);
1382  if (gnc_commodity_equiv(xaccAccountGetCommodity(s->acc), base_currency))
1383  return xaccSplitGetAmount(s);
1384 
1385  PERR ("inappropriate base currency %s "
1386  "given split currency=%s and commodity=%s\n",
1387  gnc_commodity_get_printname(base_currency),
1390  return gnc_numeric_zero();
1391 }
1392 
1393 /********************************************************************\
1394 \********************************************************************/
1395 
1396 gnc_numeric
1397 xaccSplitConvertAmount (const Split *split, const Account * account)
1398 {
1399  gnc_commodity *acc_com, *to_commodity;
1400  Transaction *txn;
1401  gnc_numeric amount, value, convrate;
1402  Account * split_acc;
1403 
1404  amount = xaccSplitGetAmount (split);
1405 
1406  /* If this split is attached to this account, OR */
1407  split_acc = xaccSplitGetAccount (split);
1408  if (split_acc == account)
1409  return amount;
1410 
1411  /* If split->account->commodity == to_commodity, return the amount */
1412  acc_com = xaccAccountGetCommodity (split_acc);
1413  to_commodity = xaccAccountGetCommodity (account);
1414  if (acc_com && gnc_commodity_equal (acc_com, to_commodity))
1415  return amount;
1416 
1417  /* Ok, this split is not for the viewed account, and the commodity
1418  * does not match. So we need to do some conversion.
1419  *
1420  * First, we can cheat. If this transaction is balanced and has
1421  * exactly two splits, then we can implicitly determine the exchange
1422  * rate and just return the 'other' split amount.
1423  */
1424  txn = xaccSplitGetParent (split);
1425  if (txn && xaccTransIsBalanced (txn))
1426  {
1427  const Split *osplit = xaccSplitGetOtherSplit (split);
1428 
1429  if (osplit)
1430  {
1431  gnc_commodity* split_comm =
1433  if (!gnc_commodity_equal(to_commodity, split_comm))
1434  {
1435  gchar guidstr[GUID_ENCODING_LENGTH+1];
1436  guid_to_string_buff(xaccSplitGetGUID(osplit),guidstr);
1437  PERR("The split's (%s) amount can't be converted from %s into %s.",
1438  guidstr,
1439  gnc_commodity_get_mnemonic(split_comm),
1440  gnc_commodity_get_mnemonic(to_commodity)
1441  );
1442  return gnc_numeric_zero();
1443  }
1444  return gnc_numeric_neg (xaccSplitGetAmount (osplit));
1445  }
1446  }
1447 
1448  /* ... otherwise, we need to compute the amount from the conversion
1449  * rate into _this account_. So, find the split into this account,
1450  * compute the conversion rate (based on amount/value), and then multiply
1451  * this times the split value.
1452  */
1453  value = xaccSplitGetValue (split);
1454 
1455  if (gnc_numeric_zero_p (value))
1456  {
1457  return value;
1458  }
1459 
1460  convrate = xaccTransGetAccountConvRate(txn, account);
1461  return gnc_numeric_mul (value, convrate,
1462  gnc_commodity_get_fraction (to_commodity),
1464 }
1465 
1466 /********************************************************************\
1467 \********************************************************************/
1468 
1469 gboolean
1470 xaccSplitDestroy (Split *split)
1471 {
1472  Account *acc;
1473  Transaction *trans;
1474  GncEventData ed;
1475 
1476  if (!split) return TRUE;
1477 
1478  acc = split->acc;
1479  trans = split->parent;
1480  if (acc && !qof_instance_get_destroying(acc)
1481  && !qof_instance_get_destroying(trans)
1482  && xaccTransGetReadOnly(trans))
1483  return FALSE;
1484 
1485  xaccTransBeginEdit(trans);
1486  ed.node = split;
1487  ed.idx = xaccTransGetSplitIndex(trans, split);
1488  qof_instance_set_dirty(QOF_INSTANCE(split));
1489  qof_instance_set_destroying(split, TRUE);
1490  qof_event_gen(&trans->inst, GNC_EVENT_ITEM_REMOVED, &ed);
1491  xaccTransCommitEdit(trans);
1492 
1493  return TRUE;
1494 }
1495 
1496 /********************************************************************\
1497 \********************************************************************/
1498 
1499 gint
1500 xaccSplitOrder (const Split *sa, const Split *sb)
1501 {
1502  int retval;
1503  int comp;
1504  const char *da, *db;
1505  gboolean action_for_num;
1506 
1507  if (sa == sb) return 0;
1508  /* nothing is always less than something */
1509  if (!sa) return -1;
1510  if (!sb) return +1;
1511 
1512  /* sort in transaction order, but use split action rather than trans num
1513  * according to book option */
1515  (xaccSplitGetBook (sa));
1516  if (action_for_num)
1517  retval = xaccTransOrder_num_action (sa->parent, sa->action,
1518  sb->parent, sb->action);
1519  else
1520  retval = xaccTransOrder (sa->parent, sb->parent);
1521  if (retval) return retval;
1522 
1523  /* otherwise, sort on memo strings */
1524  da = sa->memo ? sa->memo : "";
1525  db = sb->memo ? sb->memo : "";
1526  retval = g_utf8_collate (da, db);
1527  if (retval)
1528  return retval;
1529 
1530  /* otherwise, sort on action strings */
1531  da = sa->action ? sa->action : "";
1532  db = sb->action ? sb->action : "";
1533  retval = g_utf8_collate (da, db);
1534  if (retval != 0)
1535  return retval;
1536 
1537  /* the reconciled flag ... */
1538  if (sa->reconciled < sb->reconciled) return -1;
1539  if (sa->reconciled > sb->reconciled) return +1;
1540 
1541  /* compare amounts */
1543  if (comp < 0) return -1;
1544  if (comp > 0) return +1;
1545 
1547  if (comp < 0) return -1;
1548  if (comp > 0) return +1;
1549 
1550  /* if dates differ, return */
1551  if (sa->date_reconciled < sb->date_reconciled)
1552  return -1;
1553  else if (sa->date_reconciled > sb->date_reconciled)
1554  return 1;
1555 
1556  /* else, sort on guid - keeps sort stable. */
1557  retval = qof_instance_guid_compare(sa, sb);
1558  if (retval) return retval;
1559 
1560  return 0;
1561 }
1562 
1563 gint
1564 xaccSplitOrderDateOnly (const Split *sa, const Split *sb)
1565 {
1566  Transaction *ta, *tb;
1567 
1568  if (sa == sb) return 0;
1569  /* nothing is always less than something */
1570  if (!sa) return -1;
1571  if (!sb) return +1;
1572 
1573  ta = sa->parent;
1574  tb = sb->parent;
1575  if ( !ta && !tb ) return 0;
1576  if ( !tb ) return -1;
1577  if ( !ta ) return +1;
1578 
1579  if (ta->date_posted == tb->date_posted)
1580  return -1; // Keep the same order
1581  return (ta->date_posted > tb->date_posted) - (ta->date_posted < tb->date_posted);
1582 }
1583 
1584 static gboolean
1585 get_corr_account_split(const Split *sa, const Split **retval)
1586 {
1587  *retval = nullptr;
1588  g_return_val_if_fail(sa, FALSE);
1589 
1590  if (xaccTransCountSplits (sa->parent) > 2)
1591  return FALSE;
1592 
1593  *retval = xaccSplitGetOtherSplit (sa);
1594  if (*retval)
1595  return TRUE;
1596  else
1597  return FALSE;
1598 }
1599 
1600 /* TODO: these static consts can be shared. */
1601 const char *
1603 {
1604  static const char *split_const = nullptr;
1605  const Split *other_split;
1606 
1607  if (!get_corr_account_split(sa, &other_split))
1608  {
1609  if (!split_const)
1610  split_const = _("-- Split Transaction --");
1611 
1612  return split_const;
1613  }
1614 
1615  return xaccAccountGetName(other_split->acc);
1616 }
1617 
1618 char *
1620 {
1621  static const char *split_const = nullptr;
1622  const Split *other_split;
1623 
1624  if (!get_corr_account_split(sa, &other_split))
1625  {
1626  if (!split_const)
1627  split_const = _("-- Split Transaction --");
1628 
1629  return g_strdup(split_const);
1630  }
1631  return gnc_account_get_full_name(other_split->acc);
1632 }
1633 
1634 const char *
1636 {
1637  static const char *split_const = nullptr;
1638  const Split *other_split;
1639 
1640  if (!get_corr_account_split(sa, &other_split))
1641  {
1642  if (!split_const)
1643  split_const = C_("Displayed account code of the other account in a multi-split transaction", "Split");
1644 
1645  return split_const;
1646  }
1647  return xaccAccountGetCode(other_split->acc);
1648 }
1649 
1650 /* TODO: It's not too hard to make this function avoid the malloc/free. */
1651 int
1652 xaccSplitCompareAccountFullNames(const Split *sa, const Split *sb)
1653 {
1654  Account *aa, *ab;
1655  if (sa == sb) return 0;
1656  if (!sa) return -1;
1657  if (!sb) return 1;
1658 
1659  aa = sa->acc;
1660  ab = sb->acc;
1661  if (aa == ab) return 0;
1662 
1663  auto path_a = gnc_account_get_all_parents (aa);
1664  auto path_b = gnc_account_get_all_parents (ab);
1665  auto mismatch_pair = std::mismatch (path_a.rbegin(), path_a.rend(),
1666  path_b.rbegin(), path_b.rend());
1667 
1668  return mismatch_pair.first == path_a.rend() ? -1
1669  : mismatch_pair.second == path_b.rend() ? 1
1670  : g_utf8_collate (xaccAccountGetName (*mismatch_pair.first),
1671  xaccAccountGetName (*mismatch_pair.second));
1672 }
1673 
1674 
1675 int
1676 xaccSplitCompareAccountCodes(const Split *sa, const Split *sb)
1677 {
1678  Account *aa, *ab;
1679  if (!sa && !sb) return 0;
1680  if (!sa) return -1;
1681  if (!sb) return 1;
1682 
1683  aa = sa->acc;
1684  ab = sb->acc;
1685 
1686  return g_strcmp0(xaccAccountGetCode(aa), xaccAccountGetCode(ab));
1687 }
1688 
1689 int
1690 xaccSplitCompareOtherAccountFullNames(const Split *sa, const Split *sb)
1691 {
1692  char *ca, *cb;
1693  int retval;
1694  if (!sa && !sb) return 0;
1695  if (!sa) return -1;
1696  if (!sb) return 1;
1697 
1698  /* doesn't matter what separator we use
1699  * as long as they are the same
1700  */
1701 
1704  retval = g_strcmp0(ca, cb);
1705  g_free(ca);
1706  g_free(cb);
1707  return retval;
1708 }
1709 
1710 int
1711 xaccSplitCompareOtherAccountCodes(const Split *sa, const Split *sb)
1712 {
1713  const char *ca, *cb;
1714  if (!sa && !sb) return 0;
1715  if (!sa) return -1;
1716  if (!sb) return 1;
1717 
1718  ca = xaccSplitGetCorrAccountCode(sa);
1719  cb = xaccSplitGetCorrAccountCode(sb);
1720  return g_strcmp0(ca, cb);
1721 }
1722 
1723 static void
1724 qofSplitSetMemo (Split *split, const char* memo)
1725 {
1726  g_return_if_fail(split);
1727  CACHE_REPLACE(split->memo, memo);
1728 }
1729 
1730 void
1731 xaccSplitSetMemo (Split *split, const char *memo)
1732 {
1733  if (!split || !memo) return;
1734  xaccTransBeginEdit (split->parent);
1735 
1736  CACHE_REPLACE(split->memo, memo);
1737  qof_instance_set_dirty(QOF_INSTANCE(split));
1738  xaccTransCommitEdit(split->parent);
1739 
1740 }
1741 
1742 static void
1743 qofSplitSetAction (Split *split, const char *actn)
1744 {
1745  g_return_if_fail(split);
1746  CACHE_REPLACE(split->action, actn);
1747 }
1748 
1749 void
1750 xaccSplitSetAction (Split *split, const char *actn)
1751 {
1752  if (!split || !actn) return;
1753  xaccTransBeginEdit (split->parent);
1754 
1755  CACHE_REPLACE(split->action, actn);
1756  qof_instance_set_dirty(QOF_INSTANCE(split));
1757  xaccTransCommitEdit(split->parent);
1758 
1759 }
1760 
1761 static void
1762 qofSplitSetReconcile (Split *split, char recn)
1763 {
1764  g_return_if_fail(split);
1765  switch (recn)
1766  {
1767  case NREC:
1768  case CREC:
1769  case YREC:
1770  case FREC:
1771  case VREC:
1772  split->reconciled = recn;
1773  mark_split (split);
1774  xaccAccountRecomputeBalance (split->acc);
1775  break;
1776  default:
1777  PERR("Bad reconciled flag");
1778  break;
1779  }
1780 }
1781 
1782 void
1783 xaccSplitSetReconcile (Split *split, char recn)
1784 {
1785  if (!split || split->reconciled == recn) return;
1786  xaccTransBeginEdit (split->parent);
1787 
1788  switch (recn)
1789  {
1790  case NREC:
1791  case CREC:
1792  case YREC:
1793  case FREC:
1794  case VREC:
1795  split->reconciled = recn;
1796  mark_split (split);
1797  qof_instance_set_dirty(QOF_INSTANCE(split));
1798  xaccAccountRecomputeBalance (split->acc);
1799  break;
1800  default:
1801  PERR("Bad reconciled flag");
1802  break;
1803  }
1804  xaccTransCommitEdit(split->parent);
1805 
1806 }
1807 
1808 void
1810 {
1811  if (!split) return;
1812  xaccTransBeginEdit (split->parent);
1813 
1814  split->date_reconciled = secs;
1815  qof_instance_set_dirty(QOF_INSTANCE(split));
1816  xaccTransCommitEdit(split->parent);
1817 
1818 }
1819 
1820 
1821 /*################## Added for Reg2 #################*/
1822 time64
1823 xaccSplitGetDateReconciled (const Split * split)
1824 {
1825  return split ? split->date_reconciled : 0;
1826 }
1827 /*################## Added for Reg2 #################*/
1828 
1829 /********************************************************************\
1830 \********************************************************************/
1831 
1832 /* return the parent transaction of the split */
1833 Transaction *
1834 xaccSplitGetParent (const Split *split)
1835 {
1836  return split ? split->parent : nullptr;
1837 }
1838 
1839 void
1840 xaccSplitSetParent(Split *s, Transaction *t)
1841 {
1842  Transaction *old_trans;
1843  GncEventData ed;
1844 
1845  g_return_if_fail(s);
1846  if (s->parent == t) return;
1847 
1848  if (s->parent != s->orig_parent && s->orig_parent != t)
1849  PERR("You may not add the split to more than one transaction"
1850  " during the BeginEdit/CommitEdit block.");
1851  xaccTransBeginEdit(t);
1852  old_trans = s->parent;
1853 
1854  xaccTransBeginEdit(old_trans);
1855 
1856  ed.node = s;
1857  if (old_trans)
1858  {
1859  ed.idx = xaccTransGetSplitIndex(old_trans, s);
1860  qof_event_gen(&old_trans->inst, GNC_EVENT_ITEM_REMOVED, &ed);
1861  }
1862  s->parent = t;
1863 
1864  xaccTransCommitEdit(old_trans);
1865  qof_instance_set_dirty(QOF_INSTANCE(s));
1866 
1867  if (t)
1868  {
1869  /* Convert split to new transaction's commodity denominator */
1871 
1872  /* add ourselves to the new transaction's list of pending splits. */
1873  if (nullptr == g_list_find(t->splits, s))
1874  t->splits = g_list_append(t->splits, s);
1875 
1876  ed.idx = -1; /* unused */
1877  qof_event_gen(&t->inst, GNC_EVENT_ITEM_ADDED, &ed);
1878  }
1880 }
1881 
1882 
1883 GNCLot *
1884 xaccSplitGetLot (const Split *split)
1885 {
1886  return split ? split->lot : nullptr;
1887 }
1888 
1889 void
1890 xaccSplitSetLot(Split* split, GNCLot* lot)
1891 {
1892  xaccTransBeginEdit (split->parent);
1893  split->lot = lot;
1894  qof_instance_set_dirty(QOF_INSTANCE(split));
1895  xaccTransCommitEdit(split->parent);
1896 }
1897 
1898 const char *
1899 xaccSplitGetMemo (const Split *split)
1900 {
1901  return split ? split->memo : nullptr;
1902 }
1903 
1904 const char *
1905 xaccSplitGetAction (const Split *split)
1906 {
1907  return split ? split->action : nullptr;
1908 }
1909 
1910 char
1911 xaccSplitGetReconcile (const Split *split)
1912 {
1913  return split ? split->reconciled : ' ';
1914 }
1915 
1916 
1917 gnc_numeric
1918 xaccSplitGetAmount (const Split * split)
1919 {
1920  return split ? split->amount : gnc_numeric_zero();
1921 }
1922 
1923 gnc_numeric
1924 xaccSplitGetValue (const Split * split)
1925 {
1926  return split ? split->value : gnc_numeric_zero();
1927 }
1928 
1929 gnc_numeric
1930 xaccSplitGetSharePrice (const Split * split)
1931 {
1932  gnc_numeric amt, val, price;
1933  if (!split) return gnc_numeric_create(0, 1);
1934 
1935 
1936  /* if amount == 0, return 0
1937  * otherwise return value/amount
1938  */
1939 
1940  amt = xaccSplitGetAmount(split);
1941  val = xaccSplitGetValue(split);
1942  if (gnc_numeric_zero_p(amt))
1943  return gnc_numeric_create(0, 1);
1944 
1945  price = gnc_numeric_div(val, amt,
1948 
1949  /* During random checks we can get some very weird prices. Let's
1950  * handle some overflow and other error conditions by returning
1951  * zero. But still print an error to let us know it happened.
1952  */
1953  if (gnc_numeric_check(price))
1954  {
1955  PERR("Computing share price failed (%d): [ %" G_GINT64_FORMAT " / %"
1956  G_GINT64_FORMAT " ] / [ %" G_GINT64_FORMAT " / %" G_GINT64_FORMAT " ]",
1957  gnc_numeric_check(price), val.num, val.denom, amt.num, amt.denom);
1958  return gnc_numeric_create(0, 1);
1959  }
1960 
1961  return price;
1962 }
1963 
1964 /********************************************************************\
1965 \********************************************************************/
1966 
1967 QofBook *
1968 xaccSplitGetBook (const Split *split)
1969 {
1970  return qof_instance_get_book(QOF_INSTANCE(split));
1971 }
1972 
1973 const char *
1974 xaccSplitGetType(const Split *s)
1975 {
1976  if (!s) return nullptr;
1977 
1978  auto type{qof_instance_get_path_kvp<const char*> (QOF_INSTANCE(s), {"split-type"})};
1979 
1980  if (!type || !g_strcmp0 (*type, split_type_normal))
1981  return split_type_normal;
1982 
1983  if (!g_strcmp0 (*type, split_type_stock_split))
1984  return split_type_stock_split;
1985 
1986  PERR ("unexpected split-type %s, reset to normal.", *type);
1987  return split_type_normal;
1988 }
1989 
1990 /* reconfigure a split to be a stock split - after this, you shouldn't
1991  mess with the value, just the amount. */
1992 void
1994 {
1995  xaccTransBeginEdit (s->parent);
1996 
1997  s->value = gnc_numeric_zero();
1998  qof_instance_set_path_kvp<const char*> (QOF_INSTANCE(s), g_strdup(split_type_stock_split),
1999  {"split-type"});
2000  SET_GAINS_VDIRTY(s);
2001  mark_split(s);
2002  qof_instance_set_dirty(QOF_INSTANCE(s));
2003  xaccTransCommitEdit(s->parent);
2004 }
2005 
2006 void
2007 xaccSplitAddPeerSplit (Split *split, const Split *other_split,
2008  time64 timestamp)
2009 {
2010  const GncGUID* guid;
2011 
2012  g_return_if_fail (split != nullptr);
2013  g_return_if_fail (other_split != nullptr);
2014 
2015  guid = qof_instance_get_guid (QOF_INSTANCE (other_split));
2016  xaccTransBeginEdit (split->parent);
2017  qof_instance_kvp_add_guid (QOF_INSTANCE (split), "lot-split",
2018  gnc_time(nullptr), "peer_guid", guid_copy(guid));
2019  mark_split (split);
2020  qof_instance_set_dirty (QOF_INSTANCE (split));
2021  xaccTransCommitEdit (split->parent);
2022 }
2023 
2024 gboolean
2025 xaccSplitHasPeers (const Split *split)
2026 {
2027  return qof_instance_has_slot (QOF_INSTANCE (split), "lot-split");
2028 }
2029 
2030 gboolean
2031 xaccSplitIsPeerSplit (const Split *split, const Split *other_split)
2032 {
2033  const GncGUID* guid;
2034 
2035  g_return_val_if_fail (split != nullptr, FALSE);
2036  g_return_val_if_fail (other_split != nullptr, FALSE);
2037 
2038  guid = qof_instance_get_guid (QOF_INSTANCE (other_split));
2039  return qof_instance_kvp_has_guid (QOF_INSTANCE (split), "lot-split",
2040  "peer_guid", guid);
2041 }
2042 
2043 void
2044 xaccSplitRemovePeerSplit (Split *split, const Split *other_split)
2045 {
2046  const GncGUID* guid;
2047 
2048  g_return_if_fail (split != nullptr);
2049  g_return_if_fail (other_split != nullptr);
2050 
2051  guid = qof_instance_get_guid (QOF_INSTANCE (other_split));
2052  xaccTransBeginEdit (split->parent);
2053  qof_instance_kvp_remove_guid (QOF_INSTANCE (split), "lot-split",
2054  "peer_guid", guid);
2055  mark_split (split);
2056  qof_instance_set_dirty (QOF_INSTANCE (split));
2057  xaccTransCommitEdit (split->parent);
2058 }
2059 
2060 void
2061 xaccSplitMergePeerSplits (Split *split, const Split *other_split)
2062 {
2063  xaccTransBeginEdit (split->parent);
2064  qof_instance_kvp_merge_guids (QOF_INSTANCE (split),
2065  QOF_INSTANCE (other_split), "lot-split");
2066  mark_split (split);
2067  qof_instance_set_dirty (QOF_INSTANCE (split));
2068  xaccTransCommitEdit (split->parent);
2069 }
2070 
2071 /********************************************************************\
2072 \********************************************************************/
2073 /* In the old world, the 'other split' was the other split of a
2074  * transaction that contained only two splits. In the new world,
2075  * a split may have been cut up between multiple lots, although
2076  * in a conceptual sense, if lots hadn't been used, there would be
2077  * only a pair. So we handle this conceptual case: we can still
2078  * identify, unambiguously, the 'other' split when 'this' split
2079  * as been cut up across lots. We do this by looking for the
2080  * 'lot-split' keyword, which occurs only in cut-up splits.
2081  */
2082 
2083 Split *
2084 xaccSplitGetOtherSplit (const Split *split)
2085 {
2086  Transaction *trans;
2087  Split *other = nullptr;
2088 
2089  if (!split) return nullptr;
2090  trans = split->parent;
2091  if (!trans) return nullptr;
2092 
2093  for (GList *n = xaccTransGetSplitList (trans); n; n = n->next)
2094  {
2095  Split *s = GNC_SPLIT(n->data);
2096  if ((s == split) ||
2097  (!xaccTransStillHasSplit(trans, s)) ||
2099  (qof_instance_has_slot (QOF_INSTANCE (s), "lot-split")))
2100  continue;
2101 
2102  if (other)
2103  return nullptr;
2104 
2105  other = s;
2106  }
2107  return other;
2108 }
2109 
2110 /********************************************************************\
2111 \********************************************************************/
2112 
2113 gnc_numeric
2114 xaccSplitVoidFormerAmount(const Split *split)
2115 {
2116  g_return_val_if_fail(split, gnc_numeric_zero());
2117  auto num{qof_instance_get_path_kvp<gnc_numeric> (QOF_INSTANCE(split), {void_former_amt_str})};
2118  return num ? *num : gnc_numeric_zero();
2119 }
2120 
2121 gnc_numeric
2122 xaccSplitVoidFormerValue(const Split *split)
2123 {
2124  g_return_val_if_fail(split, gnc_numeric_zero());
2125  auto num{qof_instance_get_path_kvp<gnc_numeric> (QOF_INSTANCE(split), {void_former_val_str})};
2126  return num ? *num : gnc_numeric_zero();
2127 }
2128 
2129 void
2130 xaccSplitVoid(Split *split)
2131 {
2132  g_return_if_fail (GNC_IS_SPLIT(split));
2133  qof_instance_set_path_kvp<gnc_numeric> (QOF_INSTANCE(split), xaccSplitGetAmount(split), {void_former_amt_str});
2134  qof_instance_set_path_kvp<gnc_numeric> (QOF_INSTANCE(split), xaccSplitGetValue(split), {void_former_val_str});
2135  qof_instance_set_dirty (QOF_INSTANCE(split));
2136 
2137  static gnc_numeric zero = gnc_numeric_zero();
2138  xaccSplitSetAmount (split, zero);
2139  xaccSplitSetValue (split, zero);
2140  xaccSplitSetReconcile(split, VREC);
2141 }
2142 
2143 void
2144 xaccSplitUnvoid(Split *split)
2145 {
2146  g_return_if_fail (GNC_IS_SPLIT(split));
2149  xaccSplitSetReconcile(split, NREC);
2150  qof_instance_set_path_kvp<gnc_numeric> (QOF_INSTANCE(split), {}, {void_former_amt_str});
2151  qof_instance_set_path_kvp<gnc_numeric> (QOF_INSTANCE(split), {}, {void_former_val_str});
2152  qof_instance_set_dirty (QOF_INSTANCE(split));
2153 }
2154 
2155 /********************************************************************\
2156 \********************************************************************/
2157 /* QofObject function implementation */
2158 
2159 /* Hook into the QofObject registry */
2160 
2161 #ifdef _MSC_VER
2162 /* MSVC compiler doesn't have C99 "designated initializers"
2163  * so we wrap them in a macro that is empty on MSVC. */
2164 # define DI(x) /* */
2165 #else
2166 # define DI(x) x
2167 #endif
2168 static QofObject split_object_def =
2169 {
2170  DI(.interface_version = ) QOF_OBJECT_VERSION,
2171  DI(.e_type = ) GNC_ID_SPLIT,
2172  DI(.type_label = ) "Split",
2173  DI(.create = ) (void* (*)(QofBook*))xaccMallocSplit,
2174  DI(.book_begin = ) nullptr,
2175  DI(.book_end = ) nullptr,
2176  DI(.is_dirty = ) qof_collection_is_dirty,
2177  DI(.mark_clean = ) qof_collection_mark_clean,
2178  DI(.foreach = ) qof_collection_foreach,
2179  DI(.printable = ) (const char * (*)(gpointer)) xaccSplitGetMemo,
2180  DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
2181 };
2182 
2183 static gpointer
2184 split_account_guid_getter (gpointer obj, const QofParam *p)
2185 {
2186  Split *s = GNC_SPLIT(obj);
2187  Account *acc;
2188 
2189  if (!s) return nullptr;
2190  acc = xaccSplitGetAccount (s);
2191  if (!acc) return nullptr;
2192  return ((gpointer)xaccAccountGetGUID (acc));
2193 }
2194 
2195 static double /* internal use only */
2196 DxaccSplitGetShareAmount (const Split * split)
2197 {
2198  return split ? gnc_numeric_to_double(xaccSplitGetAmount(split)) : 0.0;
2199 }
2200 
2201 static gpointer
2202 no_op (gpointer obj, const QofParam *p)
2203 {
2204  return obj;
2205 }
2206 
2207 static void
2208 qofSplitSetParentTrans(Split *s, QofInstance *ent)
2209 {
2210  Transaction *trans = (Transaction*)ent;
2211 
2212  g_return_if_fail(trans);
2213  xaccSplitSetParent(s, trans);
2214 }
2215 
2216 static void
2217 qofSplitSetAccount(Split *s, QofInstance *ent)
2218 {
2219  Account *acc = (Account*)ent;
2220 
2221  g_return_if_fail(acc);
2222  xaccSplitSetAccount(s, acc);
2223 }
2224 
2225 gboolean xaccSplitRegister (void)
2226 {
2227  static const QofParam params[] =
2228  {
2229  {
2230  SPLIT_DATE_RECONCILED, QOF_TYPE_DATE,
2233  },
2234 
2235  /* d-* are deprecated query params, should not be used in new
2236  * queries, should be removed from old queries. */
2237  {
2238  "d-share-amount", QOF_TYPE_DOUBLE,
2239  (QofAccessFunc)DxaccSplitGetShareAmount, nullptr
2240  },
2241  {
2242  "d-share-int64", QOF_TYPE_INT64,
2244  },
2245  {
2246  SPLIT_BALANCE, QOF_TYPE_NUMERIC,
2248  },
2249  {
2250  SPLIT_CLEARED_BALANCE, QOF_TYPE_NUMERIC,
2252  },
2253  {
2254  SPLIT_RECONCILED_BALANCE, QOF_TYPE_NUMERIC,
2256  },
2257  {
2258  SPLIT_MEMO, QOF_TYPE_STRING,
2259  (QofAccessFunc)xaccSplitGetMemo, (QofSetterFunc)qofSplitSetMemo
2260  },
2261  {
2262  SPLIT_ACTION, QOF_TYPE_STRING,
2263  (QofAccessFunc)xaccSplitGetAction, (QofSetterFunc)qofSplitSetAction
2264  },
2265  {
2266  SPLIT_RECONCILE, QOF_TYPE_CHAR,
2268  (QofSetterFunc)qofSplitSetReconcile
2269  },
2270  {
2271  SPLIT_AMOUNT, QOF_TYPE_NUMERIC,
2272  (QofAccessFunc)xaccSplitGetAmount, (QofSetterFunc)qofSplitSetAmount
2273  },
2274  {
2275  SPLIT_SHARE_PRICE, QOF_TYPE_NUMERIC,
2277  (QofSetterFunc)qofSplitSetSharePrice
2278  },
2279  {
2280  SPLIT_VALUE, QOF_TYPE_DEBCRED,
2281  (QofAccessFunc)xaccSplitGetValue, (QofSetterFunc)qofSplitSetValue
2282  },
2283  { SPLIT_TYPE, QOF_TYPE_STRING, (QofAccessFunc)xaccSplitGetType, nullptr },
2284  {
2285  SPLIT_VOIDED_AMOUNT, QOF_TYPE_NUMERIC,
2287  },
2288  {
2289  SPLIT_VOIDED_VALUE, QOF_TYPE_NUMERIC,
2291  },
2292  { SPLIT_LOT, GNC_ID_LOT, (QofAccessFunc)xaccSplitGetLot, nullptr },
2293  {
2294  SPLIT_TRANS, GNC_ID_TRANS,
2296  (QofSetterFunc)qofSplitSetParentTrans
2297  },
2298  {
2299  SPLIT_ACCOUNT, GNC_ID_ACCOUNT,
2300  (QofAccessFunc)xaccSplitGetAccount, (QofSetterFunc)qofSplitSetAccount
2301  },
2302  { SPLIT_ACCOUNT_GUID, QOF_TYPE_GUID, split_account_guid_getter, nullptr },
2303  /* these are no-ops to register the parameter names (for sorting) but
2304  they return an allocated object which getters cannot do. */
2305  { SPLIT_ACCT_FULLNAME, SPLIT_ACCT_FULLNAME, no_op, nullptr },
2306  { SPLIT_CORR_ACCT_NAME, SPLIT_CORR_ACCT_NAME, no_op, nullptr },
2307  { SPLIT_CORR_ACCT_CODE, SPLIT_CORR_ACCT_CODE, no_op, nullptr },
2308  { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)xaccSplitGetBook, nullptr },
2309  {
2310  QOF_PARAM_GUID, QOF_TYPE_GUID,
2312  },
2313  { nullptr },
2314  };
2315 
2316  qof_class_register (GNC_ID_SPLIT, (QofSortFunc)xaccSplitOrder, params);
2317  qof_class_register (SPLIT_ACCT_FULLNAME,
2319  qof_class_register (SPLIT_CORR_ACCT_NAME,
2321  nullptr);
2322  qof_class_register (SPLIT_CORR_ACCT_CODE,
2324 
2325  return qof_object_register (&split_object_def);
2326 }
2327 
2329 _utest_split_fill_functions (void)
2330 {
2331  SplitTestFunctions *func = g_new (SplitTestFunctions, 1);
2332 
2333  func->xaccSplitEqualCheckBal = xaccSplitEqualCheckBal;
2334  func->get_currency_denom = get_currency_denom;
2335  func->get_commodity_denom = get_commodity_denom;
2336  func->get_corr_account_split = get_corr_account_split;
2337  return func;
2338 }
2339 
2340 /************************ END OF ************************************\
2341 \************************* 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:1259
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:1307
gint xaccSplitOrder(const Split *sa, const Split *sb)
The xaccSplitOrder(sa,sb) method is useful for sorting.
Definition: Split.cpp:1500
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:2007
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:1319
void xaccSplitSetAction(Split *split, const char *actn)
The Action is an arbitrary user-assigned string.
Definition: Split.cpp:1750
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:1993
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:1676
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:1313
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account&#39;s account type.
Definition: Account.cpp:3237
gboolean xaccSplitDestroy(Split *split)
Destructor.
Definition: Split.cpp:1470
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:2716
const char * xaccAccountGetCode(const Account *acc)
Get the account&#39;s accounting code.
Definition: Account.cpp:3306
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:1911
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:579
gboolean gnc_account_remove_split(Account *acc, Split *s)
Remove the given split from an account.
Definition: Account.cpp:1975
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:1783
void xaccAccountInsertLot(Account *acc, GNCLot *lot)
The xaccAccountInsertLot() method will register the indicated lot with this account.
Definition: Account.cpp:2142
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
Definition: Split.cpp:1834
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:2044
int(* QofSortFunc)(gconstpointer, gconstpointer)
This function is the default sort function for a particular object type.
Definition: qofclass.h:223
gint 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:1690
#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:1968
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:1295
#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:1652
#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:2025
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:252
gdouble gnc_numeric_to_double(gnc_numeric n)
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:2061
gnc_numeric xaccSplitVoidFormerAmount(const Split *split)
Returns the original pre-void amount of a split.
Definition: Split.cpp:2114
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:1223
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:3275
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:2122
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:1731
#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:1711
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:1157
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:1301
#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:2281
gboolean xaccSplitIsPeerSplit(const Split *split, const Split *other_split)
Report if a split is a peer of this one.
Definition: Split.cpp:2031
char * xaccSplitGetCorrAccountFullName(const Split *sa)
These functions take a split, get the corresponding split on the "other side" of the transaction...
Definition: Split.cpp:1619
void gnc_lot_remove_split(GNCLot *lot, Split *split)
Adds a split from this lot.
Definition: gnc-lot.cpp:631
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 x, gnc_numeric y, 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:1930
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:1374
Split * xaccMallocSplit(QofBook *book)
Constructor.
Definition: Split.cpp:532
const char * xaccSplitGetCorrAccountName(const Split *sa)
document me
Definition: Split.cpp:1602
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:1945
void xaccSplitSetLot(Split *split, GNCLot *lot)
Assigns the split to a specific Lot.
Definition: Split.cpp:1890
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:1809
time64 xaccSplitGetDateReconciled(const Split *split)
Retrieve the date when the Split was reconciled.
Definition: Split.cpp:1823
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction&#39;s commodity.
Definition: Split.cpp:1924
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:3371
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:1052
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:1635
Split * xaccSplitGetOtherSplit(const Split *split)
The xaccSplitGetOtherSplit() is a convenience routine that returns the other of a pair of splits...
Definition: Split.cpp:2084
#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:1185
time64 gnc_time(time64 *tbuf)
get the current time
Definition: gnc-date.cpp:260
int xaccTransOrder(const Transaction *ta, const Transaction *tb)
The xaccTransOrder(ta,tb) method is useful for sorting.
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
Check for error signal in value.
const char * xaccSplitGetMemo(const Split *split)
Returns the memo string.
Definition: Split.cpp:1899
const char * xaccSplitGetAction(const Split *split)
Returns the action string.
Definition: Split.cpp:1905
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:1974
const char * xaccAccountGetName(const Account *acc)
Get the account&#39;s name.
Definition: Account.cpp:3259
void qof_event_gen(QofInstance *entity, QofEventId event_id, gpointer event_data)
Invoke all registered event handlers using the given arguments.
Definition: qofevent.cpp:231
#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:1884
#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:1918