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