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