30 #include <glib/gi18n.h>
33 #ifdef HAVE_SYS_TIME_H
34 # include <sys/time.h>
46 #include "TransactionP.h"
53 #include "qofinstance-p.h"
55 const char *void_former_amt_str =
"void-former-amount";
56 const char *void_former_val_str =
"void-former-value";
58 #define PRICE_SIGFIGS 6
64 #define GNC_SX_ID "sched-xaction"
65 #define GNC_SX_ACCOUNT "account"
66 #define GNC_SX_CREDIT_FORMULA "credit-formula"
67 #define GNC_SX_DEBIT_FORMULA "debit-formula"
68 #define GNC_SX_CREDIT_NUMERIC "credit-numeric"
69 #define GNC_SX_DEBIT_NUMERIC "debit-numeric"
70 #define GNC_SX_SHARES "shares"
83 PROP_SX_CREDIT_FORMULA,
84 PROP_SX_CREDIT_NUMERIC,
85 PROP_SX_DEBIT_FORMULA,
86 PROP_SX_DEBIT_NUMERIC,
100 G_DEFINE_TYPE(
Split, gnc_split, QOF_TYPE_INSTANCE)
103 gnc_split_init(
Split* split)
107 split->orig_acc = NULL;
108 split->parent = NULL;
111 split->action = CACHE_INSERT(
"");
112 split->memo = CACHE_INSERT(
"");
113 split->reconciled =
NREC;
114 split->amount = gnc_numeric_zero();
115 split->value = gnc_numeric_zero();
117 split->date_reconciled.tv_sec = 0;
118 split->date_reconciled.tv_nsec = 0;
120 split->balance = gnc_numeric_zero();
121 split->cleared_balance = gnc_numeric_zero();
122 split->reconciled_balance = gnc_numeric_zero();
124 split->gains = GAINS_STATUS_UNKNOWN;
125 split->gains_split = NULL;
129 gnc_split_dispose(GObject *splitp)
131 G_OBJECT_CLASS(gnc_split_parent_class)->dispose(splitp);
135 gnc_split_finalize(GObject* splitp)
137 G_OBJECT_CLASS(gnc_split_parent_class)->finalize(splitp);
146 gnc_split_get_property(GObject *
object,
154 g_return_if_fail(GNC_IS_SPLIT(
object));
156 split = GNC_SPLIT(
object);
160 g_value_set_string(value, split->action);
163 g_value_set_string(value, split->memo);
166 g_value_set_boxed(value, &split->value);
169 g_value_set_boxed(value, &split->amount);
171 case PROP_RECONCILE_DATE:
172 g_value_set_boxed(value, &split->date_reconciled);
175 g_value_take_object(value, split->parent);
178 g_value_take_object(value, split->acc);
181 g_value_take_object(value, split->lot);
183 case PROP_SX_CREDIT_FORMULA:
184 key = GNC_SX_ID
"/" GNC_SX_CREDIT_FORMULA;
185 qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
187 case PROP_SX_CREDIT_NUMERIC:
188 key = GNC_SX_ID
"/" GNC_SX_CREDIT_NUMERIC;
189 qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
191 case PROP_SX_DEBIT_FORMULA:
192 key = GNC_SX_ID
"/" GNC_SX_DEBIT_FORMULA;
193 qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
195 case PROP_SX_DEBIT_NUMERIC:
196 key = GNC_SX_ID
"/" GNC_SX_DEBIT_NUMERIC;
197 qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
199 case PROP_SX_ACCOUNT:
200 key = GNC_SX_ID
"/" GNC_SX_ACCOUNT;
201 qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
204 key = GNC_SX_ID
"/" GNC_SX_SHARES;
205 qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
207 case PROP_ONLINE_ACCOUNT:
209 qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
213 qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
217 qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
219 case PROP_GAINS_SPLIT:
221 qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
223 case PROP_GAINS_SOURCE:
224 key =
"gains-source";
225 qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
228 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, prop_id, pspec);
234 gnc_split_set_property(GObject *
object,
243 g_return_if_fail(GNC_IS_SPLIT(
object));
245 split = GNC_SPLIT(
object);
246 if (prop_id < PROP_RUNTIME_0 && split->parent != NULL)
247 g_assert (qof_instance_get_editlevel(split->parent));
258 number = g_value_get_boxed(value);
262 number = g_value_get_boxed(value);
265 case PROP_RECONCILE_DATE:
269 xaccSplitSetParent(split, g_value_get_object(value));
272 xaccSplitSetAccount(split, g_value_get_object(value));
277 case PROP_SX_CREDIT_FORMULA:
278 key = GNC_SX_ID
"/" GNC_SX_CREDIT_FORMULA;
279 qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
281 case PROP_SX_CREDIT_NUMERIC:
282 key = GNC_SX_ID
"/" GNC_SX_CREDIT_NUMERIC;
283 qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
285 case PROP_SX_DEBIT_FORMULA:
286 key = GNC_SX_ID
"/" GNC_SX_DEBIT_FORMULA;
287 qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
289 case PROP_SX_DEBIT_NUMERIC:
290 key = GNC_SX_ID
"/" GNC_SX_DEBIT_NUMERIC;
291 qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
293 case PROP_SX_ACCOUNT:
294 key = GNC_SX_ID
"/" GNC_SX_ACCOUNT;
295 qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
298 key = GNC_SX_ID
"/" GNC_SX_SHARES;
299 qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
301 case PROP_ONLINE_ACCOUNT:
303 qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
307 qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
311 qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
313 case PROP_GAINS_SPLIT:
315 qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
317 case PROP_GAINS_SOURCE:
318 key =
"gains-source";
319 qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
322 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, prop_id, pspec);
330 GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
332 gobject_class->dispose = gnc_split_dispose;
333 gobject_class->finalize = gnc_split_finalize;
334 gobject_class->set_property = gnc_split_set_property;
335 gobject_class->get_property = gnc_split_get_property;
337 g_object_class_install_property
340 g_param_spec_string(
"action",
342 "The action is an arbitrary string assigned "
343 "by the user. It is intended to be a short "
344 "string that contains extra information about "
349 g_object_class_install_property
352 g_param_spec_string(
"memo",
354 "The action is an arbitrary string assigned "
355 "by the user. It is intended to be a short "
356 "string that describes the purpose of "
361 g_object_class_install_property
364 g_param_spec_boxed(
"value",
366 "The value for this split in the common currency. "
367 "The value and the amount provide enough information to "
368 "calculate a conversion rate.",
372 g_object_class_install_property
375 g_param_spec_boxed(
"amount",
377 "The value for this split in the currency of its account. "
378 "The value and the amount provide enough information to "
379 "calculate a conversion rate.",
383 g_object_class_install_property
386 g_param_spec_boxed(
"reconcile-date",
388 "The date this split was reconciled.",
392 g_object_class_install_property
395 g_param_spec_object (
"transaction",
397 "The transaction that this split belongs to.",
398 GNC_TYPE_TRANSACTION,
401 g_object_class_install_property
404 g_param_spec_object (
"account",
406 "The account that this split belongs to.",
410 g_object_class_install_property
413 g_param_spec_object (
"lot",
415 "The lot that this split belongs to.",
419 g_object_class_install_property
421 PROP_SX_DEBIT_FORMULA,
422 g_param_spec_string(
"sx-debit-formula",
423 "Schedule Transaction Debit Formula",
424 "The formula used to calculate the actual debit "
425 "amount when a real split is generated from this "
430 g_object_class_install_property
432 PROP_SX_DEBIT_NUMERIC,
433 g_param_spec_boxed(
"sx-debit-numeric",
434 "Scheduled Transaction Debit Numeric",
435 "Numeric value to plug into the Debit Formula when a "
436 "real split is generated from this SX split.",
440 g_object_class_install_property
442 PROP_SX_CREDIT_FORMULA,
443 g_param_spec_string(
"sx-credit-formula",
444 "Schedule Transaction Credit Formula",
445 "The formula used to calculate the actual credit "
446 "amount when a real split is generated from this "
451 g_object_class_install_property
453 PROP_SX_CREDIT_NUMERIC,
454 g_param_spec_boxed(
"sx-credit-numeric",
455 "Scheduled Transaction Credit Numeric",
456 "Numeric value to plug into the Credit Formula when a "
457 "real split is generated from this SX split.",
465 g_object_class_install_property
468 g_param_spec_string(
"sx-shares",
469 "Scheduled Transaction Shares",
470 "Numeric value of shares to insert in a new split when "
471 "it's generated from this SX split.",
475 g_object_class_install_property
478 g_param_spec_boxed(
"sx-account",
479 "Scheduled Transaction Account",
480 "The target account for a scheduled transaction split.",
484 g_object_class_install_property
487 g_param_spec_string (
"online-id",
489 "The online account which corresponds to this "
490 "account for OFX/HCBI import",
494 g_object_class_install_property
497 g_param_spec_int64 (
"lot-split",
499 "Indicates that the split was divided into two "
500 "splits in order to balance a lot capital gains "
501 "transaction. Contains a timestamp of the action.",
502 G_MININT64, G_MAXINT64, 0,
505 g_object_class_install_property
508 g_param_spec_boxed (
"peer-guid",
510 "The other split in the division.",
514 g_object_class_install_property
517 g_param_spec_boxed (
"gains-split",
519 "The capital gains split associated with this "
520 "split when this split represents the proceeds "
521 "from the sale of a commodity inside a Lot.",
525 g_object_class_install_property
528 g_param_spec_boxed (
"gains-source",
530 "The source split for which this split this is "
548 xaccSplitReinit(
Split * split)
552 split->orig_acc = NULL;
553 split->parent = NULL;
556 CACHE_REPLACE(split->action,
"");
557 CACHE_REPLACE(split->memo,
"");
558 split->reconciled =
NREC;
559 split->amount = gnc_numeric_zero();
560 split->value = gnc_numeric_zero();
562 split->date_reconciled.tv_sec = 0;
563 split->date_reconciled.tv_nsec = 0;
565 split->balance = gnc_numeric_zero();
566 split->cleared_balance = gnc_numeric_zero();
567 split->reconciled_balance = gnc_numeric_zero();
569 if (split->inst.kvp_data)
572 qof_instance_set_idata(split, 0);
574 split->gains = GAINS_STATUS_UNKNOWN;
575 split->gains_split = NULL;
585 g_return_val_if_fail (book, NULL);
587 split = g_object_new (GNC_TYPE_SPLIT, NULL);
588 xaccInitSplit (split, book);
603 xaccDupeSplit (
const Split *s)
605 Split *split = g_object_new (GNC_TYPE_SPLIT, NULL);
611 split->inst.
e_type = NULL;
612 qof_instance_copy_guid(split, s);
615 split->parent = s->parent;
617 split->orig_acc = s->orig_acc;
620 split->memo = CACHE_INSERT(s->memo);
621 split->action = CACHE_INSERT(s->action);
625 split->reconciled = s->reconciled;
626 split->date_reconciled = s->date_reconciled;
628 split->value = s->value;
629 split->amount = s->amount;
641 xaccSplitCloneNoKvp (
const Split *s)
643 Split *split = g_object_new (GNC_TYPE_SPLIT, NULL);
645 split->parent = NULL;
646 split->memo = CACHE_INSERT(s->memo);
647 split->action = CACHE_INSERT(s->action);
648 split->reconciled = s->reconciled;
649 split->date_reconciled = s->date_reconciled;
650 split->value = s->value;
651 split->amount = s->amount;
652 split->balance = s->balance;
653 split->cleared_balance = s->cleared_balance;
654 split->reconciled_balance = s->reconciled_balance;
656 split->gains = GAINS_STATUS_UNKNOWN;
657 split->gains_split = NULL;
671 xaccSplitCopyKvp (
const Split *from,
Split *to)
688 if (!from_split || !to_split)
return;
701 qof_instance_set_dirty(QOF_INSTANCE(to_split));
708 #ifdef DUMP_FUNCTIONS
710 xaccSplitDump (
const Split *split,
const char *tag)
712 printf(
" %s Split %p", tag, split);
714 printf(
" Account: %p (%s)\n", split->acc,
716 printf(
" Commod: %s\n",
720 printf(
" Lot: %p\n", split->lot);
721 printf(
" Parent: %p\n", split->parent);
722 printf(
" Gains: %p\n", split->gains_split);
723 printf(
" Memo: %s\n", split->memo ? split->memo :
"(null)");
724 printf(
" Action: %s\n", split->action ? split->action :
"(null)");
725 printf(
" KVP Data: %p\n", split->inst.kvp_data);
726 printf(
" Recncld: %c (date %s)\n", split->reconciled,
732 printf(
" RBalance: %s\n",
742 xaccFreeSplit (
Split *split)
747 if (((
char *) 1) == split->memo)
749 PERR (
"double-free %p", split);
752 CACHE_REMOVE(split->memo);
753 CACHE_REMOVE(split->action);
756 split->memo = (
char *) 1;
757 split->action = NULL;
758 split->reconciled =
NREC;
759 split->amount = gnc_numeric_zero();
760 split->value = gnc_numeric_zero();
761 split->parent = NULL;
764 split->orig_acc = NULL;
766 split->date_reconciled.tv_sec = 0;
767 split->date_reconciled.tv_nsec = 0;
768 if (split->inst.kvp_data)
770 split->inst.kvp_data = NULL;
773 if (split->gains_split) split->gains_split->gains_split = NULL;
775 g_object_unref(split);
778 void mark_split (
Split *s)
782 g_object_set(s->acc,
"sort-dirty", TRUE,
"balance-dirty", TRUE, NULL);
803 PINFO (
"%sbalances differ: %s vs %s", tag, str_a, str_b);
816 gboolean check_guids,
817 gboolean check_balances,
818 gboolean check_txn_splits)
822 if (!sa && !sb)
return TRUE;
826 PINFO (
"one is NULL");
830 if (sa == sb)
return TRUE;
838 PINFO (
"GUIDs differ");
844 if ((same_book && sa->memo != sb->memo) || (!same_book && g_strcmp0(sa->memo, sb->memo) != 0))
846 PINFO (
"memos differ: (%p)%s vs (%p)%s",
847 sa->memo, sa->memo, sb->memo, sb->memo);
851 if ((same_book && sa->action != sb->action) || (!same_book && g_strcmp0(sa->action, sb->action) != 0))
853 PINFO (
"actions differ: %s vs %s", sa->action, sb->action);
865 PINFO (
"kvp frames differ:\n%s\n\nvs\n\n%s", frame_a, frame_b);
873 if (sa->reconciled != sb->reconciled)
875 PINFO (
"reconcile flags differ: %c vs %c", sa->reconciled, sb->reconciled);
879 if (
timespec_cmp(&(sa->date_reconciled), &(sb->date_reconciled)))
881 PINFO (
"reconciled date differs");
893 PINFO (
"amounts differ: %s vs %s", str_a, str_b);
909 PINFO (
"values differ: %s vs %s", str_a, str_b);
919 if (!xaccSplitEqualCheckBal (
"", sa->balance, sb->balance))
921 if (!xaccSplitEqualCheckBal (
"cleared ", sa->cleared_balance,
922 sb->cleared_balance))
924 if (!xaccSplitEqualCheckBal (
"reconciled ", sa->reconciled_balance,
925 sb->reconciled_balance))
929 if (!
xaccTransEqual(sa->parent, sb->parent, check_guids, check_txn_splits,
930 check_balances, FALSE))
932 PINFO (
"transactions differ");
945 xaccSplitListGetUniqueTransactions(
const GList *splits)
948 GList *transList = NULL;
950 for(snode = splits; snode; snode = snode->next)
954 GList *item = g_list_find (transList, trans);
956 transList = g_list_append (transList, trans);
970 return s ? s->acc : NULL;
978 g_return_if_fail(s && acc);
986 qof_instance_set_dirty(QOF_INSTANCE(s));
994 PERR(
"commit error: %d", errcode);
995 gnc_engine_signal_commit_error( errcode );
1000 xaccSplitCommitEdit(
Split *s)
1005 g_return_if_fail(s);
1009 orig_acc = s->orig_acc;
1011 if (GNC_IS_ACCOUNT(s->acc))
1017 gnc_lot_remove_split (s->lot, s);
1024 PERR(
"Account lost track of moved or deleted split.");
1040 PERR(
"Account grabbed split prematurely.");
1045 if (s->parent != s->orig_parent)
1055 qof_event_gen (QOF_INSTANCE(s->lot), QOF_EVENT_MODIFY, NULL);
1061 s->orig_acc = s->acc;
1062 s->orig_parent = s->parent;
1069 g_object_set(acc,
"sort-dirty", TRUE,
"balance-dirty", TRUE, NULL);
1076 xaccSplitRollbackEdit(
Split *s)
1082 if (s->acc != s->orig_acc)
1083 s->acc = s->orig_acc;
1089 qof_instance_set_destroying(s, FALSE);
1097 xaccSplitSetParent(s, s->orig_parent);
1107 if (!guid || !book)
return NULL;
1123 xaccSplitDetermineGainStatus (
Split *split)
1128 if (GAINS_STATUS_UNKNOWN != split->gains)
return;
1133 split->gains = GAINS_STATUS_A_VDIRTY | GAINS_STATUS_DATE_DIRTY;
1134 split->gains_split = other;
1138 val = kvp_frame_get_slot (split->inst.kvp_data,
"gains-source");
1142 split->gains = GAINS_STATUS_A_VDIRTY | GAINS_STATUS_DATE_DIRTY;
1148 split->gains = GAINS_STATUS_GAINS;
1151 split->gains_split = other;
1159 get_currency_denom(
const Split * s)
1165 else if (!s->parent || !s->parent->common_currency)
1176 get_commodity_denom(
const Split * s)
1207 SET_GAINS_A_VDIRTY(s);
1209 qof_instance_set_dirty(QOF_INSTANCE(s));
1217 g_return_if_fail(split);
1219 price, get_currency_denom(split),
1231 price, get_currency_denom(s),
1234 SET_GAINS_VDIRTY(s);
1236 qof_instance_set_dirty(QOF_INSTANCE(s));
1244 g_return_if_fail(split);
1252 split->amount = amt;
1262 ENTER (
"(split=%p) old amt=%" G_GINT64_FORMAT
"/%" G_GINT64_FORMAT
1263 " new amt=%" G_GINT64_FORMAT
"/%" G_GINT64_FORMAT, s,
1264 s->amount.num, s->amount.denom, amt.num, amt.denom);
1276 SET_GAINS_ADIRTY(s);
1278 qof_instance_set_dirty(QOF_INSTANCE(s));
1286 g_return_if_fail(split);
1300 ENTER (
"(split=%p) old val=%" G_GINT64_FORMAT
"/%" G_GINT64_FORMAT
1301 " new val=%" G_GINT64_FORMAT
"/%" G_GINT64_FORMAT, s,
1302 s->value.num, s->value.denom, amt.num, amt.denom);
1312 SET_GAINS_VDIRTY(s);
1314 qof_instance_set_dirty(QOF_INSTANCE(s));
1325 return s ? s->balance : gnc_numeric_zero();
1331 return s ? s->cleared_balance : gnc_numeric_zero();
1337 return s ? s->reconciled_balance : gnc_numeric_zero();
1352 PERR (
"split must have a parent account");
1367 get_commodity_denom(s),
1371 get_currency_denom(s),
1381 PERR (
"inappropriate base currency %s "
1382 "given split currency=%s and commodity=%s\n",
1389 SET_GAINS_A_VDIRTY(s);
1391 qof_instance_set_dirty(QOF_INSTANCE(s));
1398 if (!s || !s->acc || !s->parent)
return gnc_numeric_zero();
1407 PERR (
"inappropriate base currency %s "
1408 "given split currency=%s and commodity=%s\n",
1412 return gnc_numeric_zero();
1419 xaccSplitConvertAmount (
const Split *split,
const Account * account)
1430 if (split_acc == account)
1459 PERR(
"The split's (%s) amount can't be converted from %s into %s.",
1464 return gnc_numeric_zero();
1482 convrate = xaccTransGetAccountConvRate(txn, account);
1498 if (!split)
return TRUE;
1501 trans = split->parent;
1509 qof_instance_set_dirty(QOF_INSTANCE(split));
1510 qof_instance_set_destroying(split, TRUE);
1526 gboolean action_for_num;
1528 if (sa == sb)
return 0;
1539 sb->parent, sb->action);
1542 if (retval)
return retval;
1545 da = sa->memo ? sa->memo :
"";
1546 db = sb->memo ? sb->memo :
"";
1547 retval = g_utf8_collate (da, db);
1552 da = sa->action ? sa->action :
"";
1553 db = sb->action ? sb->action :
"";
1554 retval = g_utf8_collate (da, db);
1559 if (sa->reconciled < sb->reconciled)
return -1;
1560 if (sa->reconciled > sb->reconciled)
return +1;
1564 if (comp < 0)
return -1;
1565 if (comp > 0)
return +1;
1568 if (comp < 0)
return -1;
1569 if (comp > 0)
return +1;
1572 DATE_CMP(sa, sb, date_reconciled);
1576 if (retval)
return retval;
1582 xaccSplitOrderDateOnly (
const Split *sa,
const Split *sb)
1586 if (sa == sb)
return 0;
1593 if ( !ta && !tb )
return 0;
1594 if ( !tb )
return -1;
1595 if ( !ta )
return +1;
1598 DATE_CMP(ta, tb, date_posted);
1605 get_corr_account_split(
const Split *sa,
const Split **retval)
1608 const Split *current_split;
1611 gboolean sa_value_positive, current_value_positive, seen_one = FALSE;
1614 g_return_val_if_fail(sa, FALSE);
1619 for (node = sa->parent->splits; node; node = node->next)
1621 current_split = node->data;
1622 if (current_split == sa)
continue;
1624 if (!xaccTransStillHasSplit(sa->parent, current_split))
continue;
1627 if ((sa_value_positive && !current_value_positive) ||
1628 (!sa_value_positive && current_value_positive))
1637 *retval = current_split;
1649 static const char *split_const = NULL;
1650 const Split *other_split;
1652 if (!get_corr_account_split(sa, &other_split))
1655 split_const = _(
"-- Split Transaction --");
1666 static const char *split_const = NULL;
1667 const Split *other_split;
1669 if (!get_corr_account_split(sa, &other_split))
1672 split_const = _(
"-- Split Transaction --");
1674 return g_strdup(split_const);
1682 static const char *split_const = NULL;
1683 const Split *other_split;
1685 if (!get_corr_account_split(sa, &other_split))
1689 split_const = Q_(
"Displayed account code of the other account in a multi-split transaction|Split");
1701 char *full_a, *full_b;
1703 if (!sa && !sb)
return 0;
1711 retval = g_utf8_collate(full_a, full_b);
1722 if (!sa && !sb)
return 0;
1737 if (!sa && !sb)
return 0;
1747 retval = g_strcmp0(ca, cb);
1756 const char *ca, *cb;
1757 if (!sa && !sb)
return 0;
1763 return g_strcmp0(ca, cb);
1767 qofSplitSetMemo (
Split *split,
const char* memo)
1769 g_return_if_fail(split);
1770 CACHE_REPLACE(split->memo, memo);
1776 if (!split || !memo)
return;
1779 CACHE_REPLACE(split->memo, memo);
1780 qof_instance_set_dirty(QOF_INSTANCE(split));
1786 qofSplitSetAction (
Split *split,
const char *actn)
1788 g_return_if_fail(split);
1789 CACHE_REPLACE(split->action, actn);
1795 if (!split || !actn)
return;
1798 CACHE_REPLACE(split->action, actn);
1799 qof_instance_set_dirty(QOF_INSTANCE(split));
1805 qofSplitSetReconcile (
Split *split,
char recn)
1807 g_return_if_fail(split);
1815 split->reconciled = recn;
1820 PERR(
"Bad reconciled flag");
1828 if (!split || split->reconciled == recn)
return;
1838 split->reconciled = recn;
1840 qof_instance_set_dirty(QOF_INSTANCE(split));
1844 PERR(
"Bad reconciled flag");
1857 split->date_reconciled.tv_sec = secs;
1858 split->date_reconciled.tv_nsec = 0;
1859 qof_instance_set_dirty(QOF_INSTANCE(split));
1867 if (!split || !ts)
return;
1870 split->date_reconciled = *ts;
1871 qof_instance_set_dirty(QOF_INSTANCE(split));
1879 if (!split || !ts)
return;
1880 *ts = (split->date_reconciled);
1887 return split ? split->date_reconciled : ts;
1894 return split ? split->date_reconciled.tv_sec : 0;
1905 return split ? split->parent : NULL;
1914 g_return_if_fail(s);
1915 if (s->parent == t)
return;
1917 if (s->parent != s->orig_parent && s->orig_parent != t)
1918 PERR(
"You may not add the split to more than one transaction"
1919 " during the BeginEdit/CommitEdit block.");
1921 old_trans = s->parent;
1929 qof_event_gen(&old_trans->inst, GNC_EVENT_ITEM_REMOVED, &ed);
1934 qof_instance_set_dirty(QOF_INSTANCE(s));
1942 if (NULL == g_list_find(t->splits, s))
1943 t->splits = g_list_append(t->splits, s);
1955 return split ? split->lot : NULL;
1963 qof_instance_set_dirty(QOF_INSTANCE(split));
1970 return split ? split->memo : NULL;
1976 return split ? split->action : NULL;
1982 return split ? split->reconciled :
' ';
1989 return split ? split->amount : gnc_numeric_zero();
1995 return split ? split->value : gnc_numeric_zero();
2002 if (!split)
return gnc_numeric_create(1, 1);
2015 return gnc_numeric_create(1, 1);
2016 return gnc_numeric_create(0, 1);
2029 PERR(
"Computing share price failed (%d): [ %" G_GINT64_FORMAT
" / %"
2030 G_GINT64_FORMAT
" ] / [ %" G_GINT64_FORMAT
" / %" G_GINT64_FORMAT
" ]",
2032 return gnc_numeric_create(0, 1);
2050 const char *split_type;
2052 if (!s)
return NULL;
2053 split_type = kvp_frame_get_string(s->inst.kvp_data,
"split-type");
2054 return split_type ? split_type :
"normal";
2064 s->value = gnc_numeric_zero();
2066 SET_GAINS_VDIRTY(s);
2068 qof_instance_set_dirty(QOF_INSTANCE(s));
2090 int count, num_splits;
2091 Split *other = NULL;
2093 gboolean trading_accts;
2095 if (!split)
return NULL;
2096 trans = split->parent;
2097 if (!trans)
return NULL;
2099 #ifdef OLD_ALGO_HAS_ONLY_TWO_SPLITS
2101 if (g_list_length (trans->splits) != 2)
return NULL;
2103 s1 = g_list_nth_data (trans->splits, 0);
2104 s2 = g_list_nth_data (trans->splits, 1);
2106 if (s1 == split)
return s2;
2113 sva = kvp_frame_get_slot (split->inst.kvp_data,
"lot-split");
2114 if (!sva && !trading_accts && (2 != count))
return NULL;
2116 for (i = 0; i < num_splits; i++)
2124 if (kvp_frame_get_slot (s->inst.kvp_data,
"lot-split"))
2129 if (trading_accts &&
2137 return (1 == count) ? other : NULL;
2146 g_return_val_if_fail(split, gnc_numeric_zero());
2147 return kvp_frame_get_numeric(split->inst.kvp_data, void_former_amt_str);
2153 g_return_val_if_fail(split, gnc_numeric_zero());
2154 return kvp_frame_get_numeric(split->inst.kvp_data, void_former_val_str);
2158 xaccSplitVoid(
Split *split)
2161 KvpFrame *frame = split->inst.kvp_data;
2175 xaccSplitUnvoid(
Split *split)
2177 KvpFrame *frame = split->inst.kvp_data;
2184 qof_instance_set_dirty (QOF_INSTANCE (split));
2203 DI(.e_type = ) GNC_ID_SPLIT,
2204 DI(.type_label = ) "
Split",
2206 DI(.book_begin = ) NULL,
2207 DI(.book_end = ) NULL,
2216 split_account_guid_getter (gpointer obj, const
QofParam *p)
2221 if (!s)
return NULL;
2223 if (!acc)
return NULL;
2228 DxaccSplitGetShareAmount (
const Split * split)
2234 no_op (gpointer obj,
const QofParam *p)
2240 qofSplitSetParentTrans(Split *s,
QofInstance *ent)
2244 g_return_if_fail(trans);
2245 xaccSplitSetParent(s, trans);
2253 g_return_if_fail(acc);
2254 xaccSplitSetAccount(s, acc);
2257 gboolean xaccSplitRegister (
void)
2262 SPLIT_DATE_RECONCILED, QOF_TYPE_DATE,
2270 "d-share-amount", QOF_TYPE_DOUBLE,
2274 "d-share-int64", QOF_TYPE_INT64,
2278 SPLIT_BALANCE, QOF_TYPE_NUMERIC,
2282 SPLIT_CLEARED_BALANCE, QOF_TYPE_NUMERIC,
2286 SPLIT_RECONCILED_BALANCE, QOF_TYPE_NUMERIC,
2290 SPLIT_MEMO, QOF_TYPE_STRING,
2294 SPLIT_ACTION, QOF_TYPE_STRING,
2298 SPLIT_RECONCILE, QOF_TYPE_CHAR,
2303 SPLIT_AMOUNT, QOF_TYPE_NUMERIC,
2307 SPLIT_SHARE_PRICE, QOF_TYPE_NUMERIC,
2312 SPLIT_VALUE, QOF_TYPE_DEBCRED,
2317 SPLIT_VOIDED_AMOUNT, QOF_TYPE_NUMERIC,
2321 SPLIT_VOIDED_VALUE, QOF_TYPE_NUMERIC,
2326 SPLIT_TRANS, GNC_ID_TRANS,
2331 SPLIT_ACCOUNT, GNC_ID_ACCOUNT,
2337 { SPLIT_ACCT_FULLNAME, SPLIT_ACCT_FULLNAME, no_op, NULL },
2338 { SPLIT_CORR_ACCT_NAME, SPLIT_CORR_ACCT_NAME, no_op, NULL },
2339 { SPLIT_CORR_ACCT_CODE, SPLIT_CORR_ACCT_CODE, no_op, NULL },
2340 { SPLIT_KVP, QOF_TYPE_KVP, (
QofAccessFunc)qof_instance_get_slots, NULL },
2343 QOF_PARAM_GUID, QOF_TYPE_GUID,
2362 _utest_split_fill_functions (
void)
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;
void xaccSplitSetValue(Split *s, gnc_numeric amt)
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
gnc_numeric xaccSplitGetClearedBalance(const Split *s)
gint xaccSplitOrder(const Split *sa, const Split *sb)
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
void xaccSplitSetBaseValue(Split *s, gnc_numeric value, const gnc_commodity *base_currency)
void xaccSplitSetAction(Split *split, const char *actn)
void kvp_frame_set_slot(KvpFrame *frame, const gchar *key, KvpValue *value)
int gnc_commodity_get_fraction(const gnc_commodity *cm)
void xaccSplitMakeStockSplit(Split *s)
Split * xaccTransGetSplit(const Transaction *trans, int i)
const char * gnc_print_date(Timespec ts)
gboolean xaccTransUseTradingAccounts(const Transaction *trans)
int xaccSplitCompareAccountCodes(const Split *sa, const Split *sb)
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
#define qof_instance_is_dirty
QofBook * qof_instance_get_book(gconstpointer)
gboolean qof_collection_is_dirty(const QofCollection *col)
QofInstance * qof_collection_lookup_entity(const QofCollection *, const GncGUID *)
#define PINFO(format, args...)
gnc_numeric xaccSplitGetReconciledBalance(const Split *s)
GNCAccountType xaccAccountGetType(const Account *acc)
gboolean xaccSplitDestroy(Split *split)
QofBackendError
The errors that can be reported to the GUI & other front-end users.
int xaccAccountGetCommoditySCU(const Account *acc)
const char * xaccAccountGetCode(const Account *acc)
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Timespec xaccSplitRetDateReconciledTS(const Split *split)
gboolean qof_instance_get_destroying(gconstpointer ptr)
void xaccSplitCopyOnto(const Split *from_split, Split *to_split)
gint kvp_frame_compare(const KvpFrame *fa, const KvpFrame *fb)
gboolean qof_book_use_split_action_for_num_field(const QofBook *book)
void qof_class_register(QofIdTypeConst obj_name, QofSortFunc default_sort_fcn, const QofParam *params)
char xaccSplitGetReconcile(const Split *split)
KvpFrame * kvp_frame_copy(const KvpFrame *frame)
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
#define kvp_frame_set_gnc_numeric
void gnc_lot_add_split(GNCLot *lot, Split *split)
Use a 64-bit unsigned int timespec.
gboolean gnc_account_remove_split(Account *acc, Split *s)
gboolean gnc_numeric_zero_p(gnc_numeric a)
void xaccSplitSetReconcile(Split *split, char recn)
void xaccAccountInsertLot(Account *acc, GNCLot *lot)
Transaction * xaccSplitGetParent(const Split *split)
API for Transactions and Splits (journal entries)
gchar * guid_to_string_buff(const GncGUID *guid, gchar *buff)
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
gint gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
gboolean xaccTransIsBalanced(const Transaction *trans)
#define QOF_OBJECT_VERSION
gchar * gnc_numeric_to_string(gnc_numeric n)
int xaccSplitCompareOtherAccountFullNames(const Split *sa, const Split *sb)
#define PERR(format, args...)
QofBook * xaccSplitGetBook(const Split *split)
int xaccTransOrder_num_action(const Transaction *ta, const char *actna, const Transaction *tb, const char *actnb)
#define ENTER(format, args...)
gnc_numeric xaccSplitGetBalance(const Split *s)
Split * xaccSplitGetCapGainsSplit(const Split *split)
void gnc_lot_set_closed_unknown(GNCLot *lot)
void qof_collection_foreach(const QofCollection *, QofInstanceForeachCB, gpointer user_data)
void xaccSplitGetDateReconciledTS(const Split *split, Timespec *ts)
void kvp_frame_delete(KvpFrame *frame)
int xaccSplitCompareAccountFullNames(const Split *sa, const Split *sb)
gboolean xaccSplitEqual(const Split *sa, const Split *sb, gboolean check_guids, gboolean check_balances, gboolean check_txn_splits)
void qof_instance_init_data(QofInstance *, QofIdType, QofBook *)
gint timespec_cmp(const Timespec *ta, const Timespec *tb)
int xaccTransCountSplits(const Transaction *trans)
#define xaccAccountGetGUID(X)
gdouble gnc_numeric_to_double(gnc_numeric n)
convert single-entry accounts to clean double-entry
gnc_numeric xaccSplitVoidFormerAmount(const Split *split)
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
guint32 qof_instance_get_idata(gconstpointer inst)
void xaccSplitSetAmount(Split *s, gnc_numeric amt)
gchar * gnc_account_get_full_name(const Account *account)
gboolean xaccTransEqual(const Transaction *ta, const Transaction *tb, gboolean check_guids, gboolean check_splits, gboolean check_balances, gboolean assume_ordered)
gnc_numeric gnc_numeric_convert(gnc_numeric n, gint64 denom, gint how)
gnc_numeric xaccSplitVoidFormerValue(const Split *split)
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
const char * gnc_numeric_errorCode_to_string(GNCNumericErrorCode error_code)
void xaccSplitSetMemo(Split *split, const char *memo)
#define GUID_ENCODING_LENGTH
int xaccSplitCompareOtherAccountCodes(const Split *sa, const Split *sb)
void xaccSplitSetSharePriceAndAmount(Split *s, gnc_numeric price, gnc_numeric amt)
void qof_instance_copy_book(gpointer ptr1, gconstpointer ptr2)
#define SPLIT_ACCOUNT_GUID
void xaccAccountRecomputeBalance(Account *acc)
int(* QofSortFunc)(gconstpointer, gconstpointer)
char * xaccSplitGetCorrAccountFullName(const Split *sa)
gboolean qof_commit_edit_part2(QofInstance *inst, void(*on_error)(QofInstance *, QofBackendError), void(*on_done)(QofInstance *), void(*on_free)(QofInstance *))
GncGUID * kvp_value_get_guid(const KvpValue *value)
void qof_collection_mark_clean(QofCollection *)
void xaccTransCommitEdit(Transaction *trans)
Additional event handling code.
gnc_numeric gnc_numeric_div(gnc_numeric x, gnc_numeric y, gint64 denom, gint how)
#define xaccSplitGetGUID(X)
void xaccTransBeginEdit(Transaction *trans)
gchar * kvp_frame_to_string(const KvpFrame *frame)
gnc_numeric xaccSplitGetSharePrice(const Split *split)
const char * xaccTransGetReadOnly(const Transaction *trans)
int xaccTransGetSplitIndex(const Transaction *trans, const Split *split)
gboolean gnc_numeric_eq(gnc_numeric a, gnc_numeric b)
All type declarations for the whole Gnucash engine.
const GncGUID * qof_entity_get_guid(gconstpointer)
gboolean qof_instance_books_equal(gconstpointer ptr1, gconstpointer ptr2)
gboolean gnc_numeric_positive_p(gnc_numeric a)
gnc_numeric xaccSplitGetBaseValue(const Split *s, const gnc_commodity *base_currency)
Split * xaccMallocSplit(QofBook *book)
const char * xaccSplitGetCorrAccountName(const Split *sa)
Encapsulate all the information about a dataset.
gboolean gnc_account_insert_split(Account *acc, Split *s)
void xaccSplitSetLot(Split *split, GNCLot *lot)
API for the transaction logger.
const char * gnc_commodity_get_printname(const gnc_commodity *cm)
void xaccSplitSetDateReconciledSecs(Split *split, time64 secs)
time64 xaccSplitGetDateReconciled(const Split *split)
gnc_numeric xaccSplitGetValue(const Split *split)
Account * xaccSplitGetAccount(const Split *s)
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
#define xaccAccountInsertSplit(acc, s)
gint qof_instance_guid_compare(const gconstpointer ptr1, const gconstpointer ptr2)
const char * xaccSplitGetCorrAccountCode(const Split *sa)
struct KvpFrameImpl KvpFrame
Split * xaccSplitGetOtherSplit(const Split *split)
#define LEAVE(format, args...)
void(* QofSetterFunc)(gpointer, gpointer)
void xaccSplitSetDateReconciledTS(Split *split, Timespec *ts)
void xaccSplitSetSharePrice(Split *s, gnc_numeric price)
int xaccTransOrder(const Transaction *ta, const Transaction *tb)
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
KvpFrame * kvp_frame_new(void)
const char * xaccSplitGetMemo(const Split *split)
const char * xaccSplitGetAction(const Split *split)
QofCollection * qof_book_get_collection(const QofBook *, QofIdType)
Account * gnc_lot_get_account(const GNCLot *lot)
gboolean qof_object_register(const QofObject *object)
const char * xaccSplitGetType(const Split *s)
const char * xaccAccountGetName(const Account *acc)
void qof_event_gen(QofInstance *entity, QofEventId event_type, gpointer event_data)
Invoke all registered event handlers using the given arguments.
#define GNC_EVENT_ITEM_ADDED
Utilities to Automatically Compute Capital Gains/Losses.
void kvp_frame_set_string(KvpFrame *frame, const gchar *path, const gchar *str)
Store a copy of the string at the indicated path.
struct KvpValueImpl KvpValue
#define GNC_HOW_DENOM_SIGFIGS(n)
Commodity handling public routines.
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
GNCLot * xaccSplitGetLot(const Split *split)
const gchar * QofLogModule
gnc_numeric xaccSplitGetAmount(const Split *split)