GnuCash  4.8a-132-gcdaeb421d+
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)
1134  {
1135  return 0;
1136  }
1137  else if (!s->parent || !s->parent->common_currency)
1138  {
1140  }
1141  else
1142  {
1143  return gnc_commodity_get_fraction (s->parent->common_currency);
1144  }
1145 }
1146 
1147 static inline int
1148 get_commodity_denom(const Split * s)
1149 {
1150  if (!s)
1151  {
1152  return 0;
1153  }
1154  else if (!s->acc)
1155  {
1157  }
1158  else
1159  {
1160  return xaccAccountGetCommoditySCU(s->acc);
1161  }
1162 }
1163 
1164 /********************************************************************\
1165 \********************************************************************/
1166 
1167 void
1168 xaccSplitSetSharePriceAndAmount (Split *s, gnc_numeric price, gnc_numeric amt)
1169 {
1170  if (!s) return;
1171  ENTER (" ");
1172  xaccTransBeginEdit (s->parent);
1173 
1174  s->amount = gnc_numeric_convert(amt, get_commodity_denom(s),
1176  s->value = gnc_numeric_mul(s->amount, price,
1177  get_currency_denom(s), GNC_HOW_RND_ROUND_HALF_UP);
1178 
1179  SET_GAINS_A_VDIRTY(s);
1180  mark_split (s);
1181  qof_instance_set_dirty(QOF_INSTANCE(s));
1182  xaccTransCommitEdit(s->parent);
1183  LEAVE ("");
1184 }
1185 
1186 static void
1187 qofSplitSetSharePrice (Split *split, gnc_numeric price)
1188 {
1189  g_return_if_fail(split);
1190  split->value = gnc_numeric_mul(xaccSplitGetAmount(split),
1191  price, get_currency_denom(split),
1193 }
1194 
1195 void
1196 xaccSplitSetSharePrice (Split *s, gnc_numeric price)
1197 {
1198  if (!s) return;
1199  ENTER (" ");
1200  xaccTransBeginEdit (s->parent);
1201 
1202  s->value = gnc_numeric_mul(xaccSplitGetAmount(s),
1203  price, get_currency_denom(s),
1205 
1206  SET_GAINS_VDIRTY(s);
1207  mark_split (s);
1208  qof_instance_set_dirty(QOF_INSTANCE(s));
1209  xaccTransCommitEdit(s->parent);
1210  LEAVE ("");
1211 }
1212 
1213 static void
1214 qofSplitSetAmount (Split *split, gnc_numeric amt)
1215 {
1216  g_return_if_fail(split);
1217  if (split->acc)
1218  {
1219  split->amount = gnc_numeric_convert(amt,
1220  get_commodity_denom(split), GNC_HOW_RND_ROUND_HALF_UP);
1221  }
1222  else
1223  {
1224  split->amount = amt;
1225  }
1226 }
1227 
1228 /* The amount of the split in the _account's_ commodity. */
1229 void
1230 xaccSplitSetAmount (Split *s, gnc_numeric amt)
1231 {
1232  if (!s) return;
1233  g_return_if_fail(gnc_numeric_check(amt) == GNC_ERROR_OK);
1234  ENTER ("(split=%p) old amt=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT
1235  " new amt=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, s,
1236  s->amount.num, s->amount.denom, amt.num, amt.denom);
1237 
1238  xaccTransBeginEdit (s->parent);
1239  if (s->acc)
1240  {
1241  s->amount = gnc_numeric_convert(amt, get_commodity_denom(s),
1243  g_assert (gnc_numeric_check (s->amount) == GNC_ERROR_OK);
1244  }
1245  else
1246  s->amount = amt;
1247 
1248  SET_GAINS_ADIRTY(s);
1249  mark_split (s);
1250  qof_instance_set_dirty(QOF_INSTANCE(s));
1251  xaccTransCommitEdit(s->parent);
1252  LEAVE("");
1253 }
1254 
1255 static void
1256 qofSplitSetValue (Split *split, gnc_numeric amt)
1257 {
1258  g_return_if_fail(split);
1259  split->value = gnc_numeric_convert(amt,
1260  get_currency_denom(split), GNC_HOW_RND_ROUND_HALF_UP);
1261  g_assert(gnc_numeric_check (split->value) != GNC_ERROR_OK);
1262 }
1263 
1264 /* The value of the split in the _transaction's_ currency. */
1265 void
1266 xaccSplitSetValue (Split *s, gnc_numeric amt)
1267 {
1268  gnc_numeric new_val;
1269  if (!s) return;
1270 
1271  g_return_if_fail(gnc_numeric_check(amt) == GNC_ERROR_OK);
1272  ENTER ("(split=%p) old val=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT
1273  " new val=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, s,
1274  s->value.num, s->value.denom, amt.num, amt.denom);
1275 
1276  xaccTransBeginEdit (s->parent);
1277  new_val = gnc_numeric_convert(amt, get_currency_denom(s),
1279  if (gnc_numeric_check(new_val) == GNC_ERROR_OK &&
1280  !(gnc_numeric_zero_p (new_val) && !gnc_numeric_zero_p (amt)))
1281  s->value = new_val;
1282  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));
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 = NULL;
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 = NULL;
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 = NULL;
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 = NULL;
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  char *full_a, *full_b;
1656  int retval;
1657  if (!sa && !sb) return 0;
1658  if (!sa) return -1;
1659  if (!sb) return 1;
1660 
1661  aa = sa->acc;
1662  ab = sb->acc;
1663  full_a = gnc_account_get_full_name(aa);
1664  full_b = gnc_account_get_full_name(ab);
1665  retval = g_utf8_collate(full_a, full_b);
1666  g_free(full_a);
1667  g_free(full_b);
1668  return retval;
1669 }
1670 
1671 
1672 int
1673 xaccSplitCompareAccountCodes(const Split *sa, const Split *sb)
1674 {
1675  Account *aa, *ab;
1676  if (!sa && !sb) return 0;
1677  if (!sa) return -1;
1678  if (!sb) return 1;
1679 
1680  aa = sa->acc;
1681  ab = sb->acc;
1682 
1683  return g_strcmp0(xaccAccountGetCode(aa), xaccAccountGetCode(ab));
1684 }
1685 
1686 int
1687 xaccSplitCompareOtherAccountFullNames(const Split *sa, const Split *sb)
1688 {
1689  char *ca, *cb;
1690  int retval;
1691  if (!sa && !sb) return 0;
1692  if (!sa) return -1;
1693  if (!sb) return 1;
1694 
1695  /* doesn't matter what separator we use
1696  * as long as they are the same
1697  */
1698 
1701  retval = g_strcmp0(ca, cb);
1702  g_free(ca);
1703  g_free(cb);
1704  return retval;
1705 }
1706 
1707 int
1708 xaccSplitCompareOtherAccountCodes(const Split *sa, const Split *sb)
1709 {
1710  const char *ca, *cb;
1711  if (!sa && !sb) return 0;
1712  if (!sa) return -1;
1713  if (!sb) return 1;
1714 
1715  ca = xaccSplitGetCorrAccountCode(sa);
1716  cb = xaccSplitGetCorrAccountCode(sb);
1717  return g_strcmp0(ca, cb);
1718 }
1719 
1720 static void
1721 qofSplitSetMemo (Split *split, const char* memo)
1722 {
1723  g_return_if_fail(split);
1724  CACHE_REPLACE(split->memo, memo);
1725 }
1726 
1727 void
1728 xaccSplitSetMemo (Split *split, const char *memo)
1729 {
1730  if (!split || !memo) return;
1731  xaccTransBeginEdit (split->parent);
1732 
1733  CACHE_REPLACE(split->memo, memo);
1734  qof_instance_set_dirty(QOF_INSTANCE(split));
1735  xaccTransCommitEdit(split->parent);
1736 
1737 }
1738 
1739 static void
1740 qofSplitSetAction (Split *split, const char *actn)
1741 {
1742  g_return_if_fail(split);
1743  CACHE_REPLACE(split->action, actn);
1744 }
1745 
1746 void
1747 xaccSplitSetAction (Split *split, const char *actn)
1748 {
1749  if (!split || !actn) return;
1750  xaccTransBeginEdit (split->parent);
1751 
1752  CACHE_REPLACE(split->action, actn);
1753  qof_instance_set_dirty(QOF_INSTANCE(split));
1754  xaccTransCommitEdit(split->parent);
1755 
1756 }
1757 
1758 static void
1759 qofSplitSetReconcile (Split *split, char recn)
1760 {
1761  g_return_if_fail(split);
1762  switch (recn)
1763  {
1764  case NREC:
1765  case CREC:
1766  case YREC:
1767  case FREC:
1768  case VREC:
1769  split->reconciled = recn;
1770  mark_split (split);
1771  xaccAccountRecomputeBalance (split->acc);
1772  break;
1773  default:
1774  PERR("Bad reconciled flag");
1775  break;
1776  }
1777 }
1778 
1779 void
1780 xaccSplitSetReconcile (Split *split, char recn)
1781 {
1782  if (!split || split->reconciled == recn) return;
1783  xaccTransBeginEdit (split->parent);
1784 
1785  switch (recn)
1786  {
1787  case NREC:
1788  case CREC:
1789  case YREC:
1790  case FREC:
1791  case VREC:
1792  split->reconciled = recn;
1793  mark_split (split);
1794  qof_instance_set_dirty(QOF_INSTANCE(split));
1795  xaccAccountRecomputeBalance (split->acc);
1796  break;
1797  default:
1798  PERR("Bad reconciled flag");
1799  break;
1800  }
1801  xaccTransCommitEdit(split->parent);
1802 
1803 }
1804 
1805 void
1807 {
1808  if (!split) return;
1809  xaccTransBeginEdit (split->parent);
1810 
1811  split->date_reconciled = secs;
1812  qof_instance_set_dirty(QOF_INSTANCE(split));
1813  xaccTransCommitEdit(split->parent);
1814 
1815 }
1816 
1817 
1818 /*################## Added for Reg2 #################*/
1819 time64
1820 xaccSplitGetDateReconciled (const Split * split)
1821 {
1822  return split ? split->date_reconciled : 0;
1823 }
1824 /*################## Added for Reg2 #################*/
1825 
1826 /********************************************************************\
1827 \********************************************************************/
1828 
1829 /* return the parent transaction of the split */
1830 Transaction *
1831 xaccSplitGetParent (const Split *split)
1832 {
1833  return split ? split->parent : NULL;
1834 }
1835 
1836 void
1837 xaccSplitSetParent(Split *s, Transaction *t)
1838 {
1839  Transaction *old_trans;
1840  GncEventData ed;
1841 
1842  g_return_if_fail(s);
1843  if (s->parent == t) return;
1844 
1845  if (s->parent != s->orig_parent && s->orig_parent != t)
1846  PERR("You may not add the split to more than one transaction"
1847  " during the BeginEdit/CommitEdit block.");
1848  xaccTransBeginEdit(t);
1849  old_trans = s->parent;
1850 
1851  xaccTransBeginEdit(old_trans);
1852 
1853  ed.node = s;
1854  if (old_trans)
1855  {
1856  ed.idx = xaccTransGetSplitIndex(old_trans, s);
1857  qof_event_gen(&old_trans->inst, GNC_EVENT_ITEM_REMOVED, &ed);
1858  }
1859  s->parent = t;
1860 
1861  xaccTransCommitEdit(old_trans);
1862  qof_instance_set_dirty(QOF_INSTANCE(s));
1863 
1864  if (t)
1865  {
1866  /* Convert split to new transaction's commodity denominator */
1868 
1869  /* add ourselves to the new transaction's list of pending splits. */
1870  if (NULL == g_list_find(t->splits, s))
1871  t->splits = g_list_append(t->splits, s);
1872 
1873  ed.idx = -1; /* unused */
1874  qof_event_gen(&t->inst, GNC_EVENT_ITEM_ADDED, &ed);
1875  }
1877 }
1878 
1879 
1880 GNCLot *
1881 xaccSplitGetLot (const Split *split)
1882 {
1883  return split ? split->lot : NULL;
1884 }
1885 
1886 void
1887 xaccSplitSetLot(Split* split, GNCLot* lot)
1888 {
1889  xaccTransBeginEdit (split->parent);
1890  split->lot = lot;
1891  qof_instance_set_dirty(QOF_INSTANCE(split));
1892  xaccTransCommitEdit(split->parent);
1893 }
1894 
1895 const char *
1896 xaccSplitGetMemo (const Split *split)
1897 {
1898  return split ? split->memo : NULL;
1899 }
1900 
1901 const char *
1902 xaccSplitGetAction (const Split *split)
1903 {
1904  return split ? split->action : NULL;
1905 }
1906 
1907 char
1908 xaccSplitGetReconcile (const Split *split)
1909 {
1910  return split ? split->reconciled : ' ';
1911 }
1912 
1913 
1914 gnc_numeric
1915 xaccSplitGetAmount (const Split * split)
1916 {
1917  return split ? split->amount : gnc_numeric_zero();
1918 }
1919 
1920 gnc_numeric
1921 xaccSplitGetValue (const Split * split)
1922 {
1923  return split ? split->value : gnc_numeric_zero();
1924 }
1925 
1926 gnc_numeric
1927 xaccSplitGetSharePrice (const Split * split)
1928 {
1929  gnc_numeric amt, val, price;
1930  if (!split) return gnc_numeric_create(1, 1);
1931 
1932 
1933  /* if amount == 0 and value == 0, then return 1.
1934  * if amount == 0 and value != 0 then return 0.
1935  * otherwise return value/amount
1936  */
1937 
1938  amt = xaccSplitGetAmount(split);
1939  val = xaccSplitGetValue(split);
1940  if (gnc_numeric_zero_p(amt))
1941  {
1942  if (gnc_numeric_zero_p(val))
1943  return gnc_numeric_create(1, 1);
1944  return gnc_numeric_create(0, 1);
1945  }
1946  price = gnc_numeric_div(val, amt,
1949 
1950  /* During random checks we can get some very weird prices. Let's
1951  * handle some overflow and other error conditions by returning
1952  * zero. But still print an error to let us know it happened.
1953  */
1954  if (gnc_numeric_check(price))
1955  {
1956  PERR("Computing share price failed (%d): [ %" G_GINT64_FORMAT " / %"
1957  G_GINT64_FORMAT " ] / [ %" G_GINT64_FORMAT " / %" G_GINT64_FORMAT " ]",
1958  gnc_numeric_check(price), val.num, val.denom, amt.num, amt.denom);
1959  return gnc_numeric_create(0, 1);
1960  }
1961 
1962  return price;
1963 }
1964 
1965 /********************************************************************\
1966 \********************************************************************/
1967 
1968 QofBook *
1969 xaccSplitGetBook (const Split *split)
1970 {
1971  return qof_instance_get_book(QOF_INSTANCE(split));
1972 }
1973 
1974 const char *
1975 xaccSplitGetType(const Split *s)
1976 {
1977  if (!s) return NULL;
1978  if (s->split_type == is_unset)
1979  {
1980  GValue v = G_VALUE_INIT;
1981  Split *split = (Split*) s;
1982  const char* type;
1983  qof_instance_get_kvp (QOF_INSTANCE (s), &v, 1, "split-type");
1984  type = G_VALUE_HOLDS_STRING (&v) ? g_value_get_string (&v) : NULL;
1985  if (!type || !g_strcmp0 (type, split_type_normal))
1986  split->split_type = (char*) split_type_normal;
1987  else if (!g_strcmp0 (type, split_type_stock_split))
1988  split->split_type = (char*) split_type_stock_split;
1989  else
1990  {
1991  PERR ("unexpected split-type %s, reset to normal.", type);
1992  split->split_type = split_type_normal;
1993  }
1994  g_value_unset (&v);
1995  }
1996  return s->split_type;
1997 }
1998 
1999 /* reconfigure a split to be a stock split - after this, you shouldn't
2000  mess with the value, just the amount. */
2001 void
2003 {
2004  GValue v = G_VALUE_INIT;
2005  xaccTransBeginEdit (s->parent);
2006 
2007  s->value = gnc_numeric_zero();
2008  g_value_init (&v, G_TYPE_STRING);
2009  g_value_set_static_string (&v, split_type_stock_split);
2010  s->split_type = split_type_stock_split;
2011  qof_instance_set_kvp (QOF_INSTANCE (s), &v, 1, "split-type");
2012  SET_GAINS_VDIRTY(s);
2013  mark_split(s);
2014  qof_instance_set_dirty(QOF_INSTANCE(s));
2015  xaccTransCommitEdit(s->parent);
2016  g_value_unset (&v);
2017 }
2018 
2019 void
2020 xaccSplitAddPeerSplit (Split *split, const Split *other_split,
2021  time64 timestamp)
2022 {
2023  const GncGUID* guid;
2024 
2025  g_return_if_fail (split != NULL);
2026  g_return_if_fail (other_split != NULL);
2027 
2028  guid = qof_instance_get_guid (QOF_INSTANCE (other_split));
2029  xaccTransBeginEdit (split->parent);
2030  qof_instance_kvp_add_guid (QOF_INSTANCE (split), "lot-split",
2031  gnc_time(NULL), "peer_guid", guid_copy(guid));
2032  mark_split (split);
2033  qof_instance_set_dirty (QOF_INSTANCE (split));
2034  xaccTransCommitEdit (split->parent);
2035 }
2036 
2037 gboolean
2038 xaccSplitHasPeers (const Split *split)
2039 {
2040  return qof_instance_has_slot (QOF_INSTANCE (split), "lot-split");
2041 }
2042 
2043 gboolean
2044 xaccSplitIsPeerSplit (const Split *split, const Split *other_split)
2045 {
2046  const GncGUID* guid;
2047 
2048  g_return_val_if_fail (split != NULL, FALSE);
2049  g_return_val_if_fail (other_split != NULL, FALSE);
2050 
2051  guid = qof_instance_get_guid (QOF_INSTANCE (other_split));
2052  return qof_instance_kvp_has_guid (QOF_INSTANCE (split), "lot-split",
2053  "peer_guid", guid);
2054 }
2055 
2056 void
2057 xaccSplitRemovePeerSplit (Split *split, const Split *other_split)
2058 {
2059  const GncGUID* guid;
2060 
2061  g_return_if_fail (split != NULL);
2062  g_return_if_fail (other_split != NULL);
2063 
2064  guid = qof_instance_get_guid (QOF_INSTANCE (other_split));
2065  xaccTransBeginEdit (split->parent);
2066  qof_instance_kvp_remove_guid (QOF_INSTANCE (split), "lot-split",
2067  "peer_guid", guid);
2068  mark_split (split);
2069  qof_instance_set_dirty (QOF_INSTANCE (split));
2070  xaccTransCommitEdit (split->parent);
2071 }
2072 
2073 void
2074 xaccSplitMergePeerSplits (Split *split, const Split *other_split)
2075 {
2076  xaccTransBeginEdit (split->parent);
2077  qof_instance_kvp_merge_guids (QOF_INSTANCE (split),
2078  QOF_INSTANCE (other_split), "lot-split");
2079  mark_split (split);
2080  qof_instance_set_dirty (QOF_INSTANCE (split));
2081  xaccTransCommitEdit (split->parent);
2082 }
2083 
2084 /********************************************************************\
2085 \********************************************************************/
2086 /* In the old world, the 'other split' was the other split of a
2087  * transaction that contained only two splits. In the new world,
2088  * a split may have been cut up between multiple lots, although
2089  * in a conceptual sense, if lots hadn't been used, there would be
2090  * only a pair. So we handle this conceptual case: we can still
2091  * identify, unambiguously, the 'other' split when 'this' split
2092  * as been cut up across lots. We do this by looking for the
2093  * 'lot-split' keyword, which occurs only in cut-up splits.
2094  */
2095 
2096 Split *
2097 xaccSplitGetOtherSplit (const Split *split)
2098 {
2099  Transaction *trans;
2100  Split *other = NULL;
2101 
2102  if (!split) return NULL;
2103  trans = split->parent;
2104  if (!trans) return NULL;
2105 
2106  for (GList *n = xaccTransGetSplitList (trans); n; n = n->next)
2107  {
2108  Split *s = n->data;
2109  if ((s == split) ||
2110  (!xaccTransStillHasSplit(trans, s)) ||
2112  (qof_instance_has_slot (QOF_INSTANCE (s), "lot-split")))
2113  continue;
2114 
2115  if (other)
2116  return NULL;
2117 
2118  other = s;
2119  }
2120  return other;
2121 }
2122 
2123 /********************************************************************\
2124 \********************************************************************/
2125 
2126 gnc_numeric
2127 xaccSplitVoidFormerAmount(const Split *split)
2128 {
2129  GValue v = G_VALUE_INIT;
2130  gnc_numeric *num = NULL;
2131  gnc_numeric retval;
2132  g_return_val_if_fail(split, gnc_numeric_zero());
2133  qof_instance_get_kvp (QOF_INSTANCE (split), &v, 1, void_former_amt_str);
2134  if (G_VALUE_HOLDS_BOXED (&v))
2135  num = (gnc_numeric*)g_value_get_boxed (&v);
2136  retval = num ? *num : gnc_numeric_zero();
2137  g_value_unset (&v);
2138  return retval;
2139 }
2140 
2141 gnc_numeric
2142 xaccSplitVoidFormerValue(const Split *split)
2143 {
2144  GValue v = G_VALUE_INIT;
2145  gnc_numeric *num = NULL;
2146  gnc_numeric retval;
2147  g_return_val_if_fail(split, gnc_numeric_zero());
2148  qof_instance_get_kvp (QOF_INSTANCE (split), &v, 1, void_former_val_str);
2149  if (G_VALUE_HOLDS_BOXED (&v))
2150  num = (gnc_numeric*)g_value_get_boxed (&v);
2151  retval = num ? *num : gnc_numeric_zero();
2152  g_value_unset (&v);
2153  return retval;
2154 }
2155 
2156 void
2157 xaccSplitVoid(Split *split)
2158 {
2159  gnc_numeric zero = gnc_numeric_zero(), num;
2160  GValue v = G_VALUE_INIT;
2161 
2162  g_value_init (&v, GNC_TYPE_NUMERIC);
2163  num = xaccSplitGetAmount(split);
2164  g_value_set_boxed (&v, &num);
2165  qof_instance_set_kvp (QOF_INSTANCE (split), &v, 1, void_former_amt_str);
2166  g_value_reset (&v);
2167  num = xaccSplitGetValue(split);
2168  g_value_set_boxed (&v, &num);
2169  qof_instance_set_kvp (QOF_INSTANCE (split), &v, 1, void_former_val_str);
2170 
2171  /* Marking dirty handled by SetAmount etc. */
2172  xaccSplitSetAmount (split, zero);
2173  xaccSplitSetValue (split, zero);
2174  xaccSplitSetReconcile(split, VREC);
2175  g_value_unset (&v);
2176 }
2177 
2178 void
2179 xaccSplitUnvoid(Split *split)
2180 {
2183  xaccSplitSetReconcile(split, NREC);
2184  qof_instance_set_kvp (QOF_INSTANCE (split), NULL, 1, void_former_amt_str);
2185  qof_instance_set_kvp (QOF_INSTANCE (split), NULL, 1, void_former_val_str);
2186  qof_instance_set_dirty (QOF_INSTANCE (split));
2187 }
2188 
2189 /********************************************************************\
2190 \********************************************************************/
2191 /* QofObject function implementation */
2192 
2193 /* Hook into the QofObject registry */
2194 
2195 #ifdef _MSC_VER
2196 /* MSVC compiler doesn't have C99 "designated initializers"
2197  * so we wrap them in a macro that is empty on MSVC. */
2198 # define DI(x) /* */
2199 #else
2200 # define DI(x) x
2201 #endif
2202 static QofObject split_object_def =
2203 {
2204  DI(.interface_version = ) QOF_OBJECT_VERSION,
2205  DI(.e_type = ) GNC_ID_SPLIT,
2206  DI(.type_label = ) "Split",
2207  DI(.create = ) (gpointer)xaccMallocSplit,
2208  DI(.book_begin = ) NULL,
2209  DI(.book_end = ) NULL,
2210  DI(.is_dirty = ) qof_collection_is_dirty,
2211  DI(.mark_clean = ) qof_collection_mark_clean,
2212  DI(.foreach = ) qof_collection_foreach,
2213  DI(.printable = ) (const char * (*)(gpointer)) xaccSplitGetMemo,
2214  DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
2215 };
2216 
2217 static gpointer
2218 split_account_guid_getter (gpointer obj, const QofParam *p)
2219 {
2220  Split *s = obj;
2221  Account *acc;
2222 
2223  if (!s) return NULL;
2224  acc = xaccSplitGetAccount (s);
2225  if (!acc) return NULL;
2226  return ((gpointer)xaccAccountGetGUID (acc));
2227 }
2228 
2229 static double /* internal use only */
2230 DxaccSplitGetShareAmount (const Split * split)
2231 {
2232  return split ? gnc_numeric_to_double(xaccSplitGetAmount(split)) : 0.0;
2233 }
2234 
2235 static gpointer
2236 no_op (gpointer obj, const QofParam *p)
2237 {
2238  return obj;
2239 }
2240 
2241 static void
2242 qofSplitSetParentTrans(Split *s, QofInstance *ent)
2243 {
2244  Transaction *trans = (Transaction*)ent;
2245 
2246  g_return_if_fail(trans);
2247  xaccSplitSetParent(s, trans);
2248 }
2249 
2250 static void
2251 qofSplitSetAccount(Split *s, QofInstance *ent)
2252 {
2253  Account *acc = (Account*)ent;
2254 
2255  g_return_if_fail(acc);
2256  xaccSplitSetAccount(s, acc);
2257 }
2258 
2259 gboolean xaccSplitRegister (void)
2260 {
2261  static const QofParam params[] =
2262  {
2263  {
2264  SPLIT_DATE_RECONCILED, QOF_TYPE_DATE,
2267  },
2268 
2269  /* d-* are deprecated query params, should not be used in new
2270  * queries, should be removed from old queries. */
2271  {
2272  "d-share-amount", QOF_TYPE_DOUBLE,
2273  (QofAccessFunc)DxaccSplitGetShareAmount, NULL
2274  },
2275  {
2276  "d-share-int64", QOF_TYPE_INT64,
2278  },
2279  {
2280  SPLIT_BALANCE, QOF_TYPE_NUMERIC,
2282  },
2283  {
2284  SPLIT_CLEARED_BALANCE, QOF_TYPE_NUMERIC,
2286  },
2287  {
2288  SPLIT_RECONCILED_BALANCE, QOF_TYPE_NUMERIC,
2290  },
2291  {
2292  SPLIT_MEMO, QOF_TYPE_STRING,
2293  (QofAccessFunc)xaccSplitGetMemo, (QofSetterFunc)qofSplitSetMemo
2294  },
2295  {
2296  SPLIT_ACTION, QOF_TYPE_STRING,
2297  (QofAccessFunc)xaccSplitGetAction, (QofSetterFunc)qofSplitSetAction
2298  },
2299  {
2300  SPLIT_RECONCILE, QOF_TYPE_CHAR,
2302  (QofSetterFunc)qofSplitSetReconcile
2303  },
2304  {
2305  SPLIT_AMOUNT, QOF_TYPE_NUMERIC,
2306  (QofAccessFunc)xaccSplitGetAmount, (QofSetterFunc)qofSplitSetAmount
2307  },
2308  {
2309  SPLIT_SHARE_PRICE, QOF_TYPE_NUMERIC,
2311  (QofSetterFunc)qofSplitSetSharePrice
2312  },
2313  {
2314  SPLIT_VALUE, QOF_TYPE_DEBCRED,
2315  (QofAccessFunc)xaccSplitGetValue, (QofSetterFunc)qofSplitSetValue
2316  },
2317  { SPLIT_TYPE, QOF_TYPE_STRING, (QofAccessFunc)xaccSplitGetType, NULL },
2318  {
2319  SPLIT_VOIDED_AMOUNT, QOF_TYPE_NUMERIC,
2321  },
2322  {
2323  SPLIT_VOIDED_VALUE, QOF_TYPE_NUMERIC,
2325  },
2326  { SPLIT_LOT, GNC_ID_LOT, (QofAccessFunc)xaccSplitGetLot, NULL },
2327  {
2328  SPLIT_TRANS, GNC_ID_TRANS,
2330  (QofSetterFunc)qofSplitSetParentTrans
2331  },
2332  {
2333  SPLIT_ACCOUNT, GNC_ID_ACCOUNT,
2334  (QofAccessFunc)xaccSplitGetAccount, (QofSetterFunc)qofSplitSetAccount
2335  },
2336  { SPLIT_ACCOUNT_GUID, QOF_TYPE_GUID, split_account_guid_getter, NULL },
2337  /* these are no-ops to register the parameter names (for sorting) but
2338  they return an allocated object which getters cannot do. */
2339  { SPLIT_ACCT_FULLNAME, SPLIT_ACCT_FULLNAME, no_op, NULL },
2340  { SPLIT_CORR_ACCT_NAME, SPLIT_CORR_ACCT_NAME, no_op, NULL },
2341  { SPLIT_CORR_ACCT_CODE, SPLIT_CORR_ACCT_CODE, no_op, NULL },
2342  { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)xaccSplitGetBook, NULL },
2343  {
2344  QOF_PARAM_GUID, QOF_TYPE_GUID,
2346  },
2347  { NULL },
2348  };
2349 
2350  qof_class_register (GNC_ID_SPLIT, (QofSortFunc)xaccSplitOrder, params);
2351  qof_class_register (SPLIT_ACCT_FULLNAME,
2353  qof_class_register (SPLIT_CORR_ACCT_NAME,
2355  NULL);
2356  qof_class_register (SPLIT_CORR_ACCT_CODE,
2358 
2359  return qof_object_register (&split_object_def);
2360 }
2361 
2363 _utest_split_fill_functions (void)
2364 {
2365  SplitTestFunctions *func = g_new (SplitTestFunctions, 1);
2366 
2367  func->xaccSplitEqualCheckBal = xaccSplitEqualCheckBal;
2368  func->get_currency_denom = get_currency_denom;
2369  func->get_commodity_denom = get_commodity_denom;
2370  func->get_corr_account_split = get_corr_account_split;
2371  return func;
2372 }
2373 
2374 /************************ END OF ************************************\
2375 \************************* 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:1266
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:1307
gint xaccSplitOrder(const Split *sa, const Split *sb)
The xaccSplitOrder(sa,sb) method is useful for sorting.
Definition: Split.c:1500
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:2020
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:1319
void xaccSplitSetAction(Split *split, const char *actn)
The Action is an arbitrary user-assigned string.
Definition: Split.c:1747
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:2002
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:1673
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
#define GNC_COMMODITY_MAX_FRACTION
Max fraction is 10^9 because 10^10 would require changing it to an int64_t.
#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:1313
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account&#39;s account type.
Definition: Account.cpp:3236
gboolean xaccSplitDestroy(Split *split)
Destructor.
Definition: Split.c: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:2682
const char * xaccAccountGetCode(const Account *acc)
Get the account&#39;s accounting code.
Definition: Account.cpp:3313
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:2567
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:1908
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:622
gboolean gnc_account_remove_split(Account *acc, Split *s)
Remove the given split from an account.
Definition: Account.cpp:1960
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:1780
void xaccAccountInsertLot(Account *acc, GNCLot *lot)
The xaccAccountInsertLot() method will register the indicated lot with this account.
Definition: Account.cpp:2124
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
Definition: Split.c:1831
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:2057
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:1142
#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:1687
#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:1969
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:1930
#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:1295
#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:425
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:1652
#define VREC
split is void
Definition: Split.h:75
Account used to record multiple commodity transactions.
Definition: Account.h:158
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:2038
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:2396
#define xaccAccountGetGUID(X)
Definition: Account.h:248
double gnc_numeric_to_double(gnc_numeric in)
Convert numeric to floating-point value.
convert single-entry accounts to clean double-entry
void xaccSplitMergePeerSplits(Split *split, const Split *other_split)
Merge the other_split&#39;s peer splits into split&#39;s peers.
Definition: Split.c:2074
gnc_numeric xaccSplitVoidFormerAmount(const Split *split)
Returns the original pre-void amount of a split.
Definition: Split.c:2127
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:1230
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:3265
gboolean xaccTransEqual(const Transaction *ta, const Transaction *tb, gboolean check_guids, gboolean check_splits, gboolean check_balances, gboolean assume_ordered)
Equality.
Definition: Transaction.c:874
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:2142
#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:1728
#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:1708
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:1168
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:1301
#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:2262
gboolean xaccSplitIsPeerSplit(const Split *split, const Split *other_split)
Report if a split is a peer of this one.
Definition: Split.c:2044
char * xaccSplitGetCorrAccountFullName(const Split *sa)
These functions take a split, get the corresponding split on the "other side" of the transaction...
Definition: Split.c:1619
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:1927
int xaccTransGetSplitIndex(const Transaction *trans, const Split *split)
Inverse of xaccTransGetSplit()
Definition: Transaction.c:2303
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:1374
Split * xaccMallocSplit(QofBook *book)
Constructor.
Definition: Split.c:534
const char * xaccSplitGetCorrAccountName(const Split *sa)
document me
Definition: Split.c: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:1924
void xaccSplitSetLot(Split *split, GNCLot *lot)
Assigns the split to a specific Lot.
Definition: Split.c:1887
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:1806
time64 xaccSplitGetDateReconciled(const Split *split)
Retrieve the date when the Split was reconciled.
Definition: Split.c:1820
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction&#39;s commodity.
Definition: Split.c:1921
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:3405
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Returns the valuation commodity of this transaction.
Definition: Transaction.c:1366
#define xaccAccountInsertSplit(acc, s)
The xaccAccountInsertSplit() method will insert the indicated split into the indicated account...
Definition: Account.h:1038
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:1635
Split * xaccSplitGetOtherSplit(const Split *split)
The xaccSplitGetOtherSplit() is a convenience routine that returns the other of a pair of splits...
Definition: Split.c:2097
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
void xaccSplitSetSharePrice(Split *s, gnc_numeric price)
Definition: Split.c:1196
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:1894
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:1896
const char * xaccSplitGetAction(const Split *split)
Returns the action string.
Definition: Split.c:1902
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
Definition: qofbook.cpp:604
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:1975
const char * xaccAccountGetName(const Account *acc)
Get the account&#39;s name.
Definition: Account.cpp:3258
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:1881
#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:1915