Financial Transactions
[GnuCash Engine: Core, Non-GUI Accounting Functions]


Files

file  Split.h
 API for Transactions and Splits (journal entries).
file  Transaction.h
 API for Transactions and Splits (journal entries).

Defines

#define GNC_TYPE_SPLIT   (gnc_split_get_type ())
#define GNC_SPLIT(o)   (G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_SPLIT, Split))
#define GNC_SPLIT_CLASS(k)   (G_TYPE_CHECK_CLASS_CAST((k), GNC_TYPE_SPLIT, SplitClass))
#define GNC_IS_SPLIT(o)   (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_SPLIT))
#define GNC_IS_SPLIT_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), GNC_TYPE_SPLIT))
#define GNC_SPLIT_GET_CLASS(o)   (G_TYPE_INSTANCE_GET_CLASS ((o), GNC_TYPE_SPLIT, SplitClass))
#define xaccSplitGetGUID(X)   qof_entity_get_guid(QOF_INSTANCE(X))
#define xaccSplitReturnGUID(X)   (X ? *(qof_entity_get_guid(QOF_INSTANCE(X))) : *(guid_null()))
#define GNC_TYPE_TRANSACTION   (gnc_transaction_get_type ())
#define GNC_TRANSACTION(o)   (G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_TRANSACTION, Transaction))
#define GNC_TRANSACTION_CLASS(k)   (G_TYPE_CHECK_CLASS_CAST((k), GNC_TYPE_TRANSACTION, TransactionClass))
#define GNC_IS_TRANSACTION(o)   (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_TRANSACTION))
#define GNC_IS_TRANSACTION_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), GNC_TYPE_TRANSACTION))
#define GNC_TRANSACTION_GET_CLASS(o)   (G_TYPE_INSTANCE_GET_CLASS ((o), GNC_TYPE_TRANSACTION, TransactionClass))
#define GNC_IS_TRANS(obj)   GNC_IS_TRANSACTION(obj)
#define GNC_TRANS(obj)   GNC_TRANSACTION(obj)
#define RECONCILED_MATCH_TYPE   "reconciled-match"
#define xaccTransGetBook(X)   qof_instance_get_book (QOF_INSTANCE(X))
#define xaccTransGetGUID(X)   qof_entity_get_guid(QOF_INSTANCE(X))
#define xaccTransReturnGUID(X)   (X ? *(qof_entity_get_guid(QOF_INSTANCE(X))) : *(guid_null()))
#define xaccTransGetSlots(X)   qof_instance_get_slots (QOF_INSTANCE(X))

Typedefs

typedef struct _SplitClass SplitClass
typedef struct _TransactionClass TransactionClass

Functions

GType gnc_split_get_type (void)
gnc_numeric xaccSplitConvertAmount (const Split *split, const Account *account)
GType gnc_transaction_get_type (void)

Detailed Description

A good overview of transactions, splits and accounts can be found in the texinfo documentation, together with an overview of how to use this API.

A good overview of transactions, splits and accounts can be found in the texinfo documentation, together with an overview of how to use this API.

Splits, or "Ledger Entries" are the fundamental accounting units. Each Split consists of an amount (number of dollar bills, number of shares, etc.), the value of that amount expressed in a (possibly) different currency than the amount, a Memo, a pointer to the parent Transaction, a pointer to the debited Account, a reconciled flag and timestamp, an "Action" field, and a key-value frame which can store arbitrary data.

Transactions embody the notion of "double entry" accounting. A Transaction consists of a date, a description, an ID number, a list of one or more Splits, and a key-value frame. The transaction also specifies the currency with which all of the splits will be valued. When double-entry rules are enforced, the sum total value of the splits are zero. If there are only two splits, then the value of one must be positive, the other negative: this denotes that one account is debited, and another is credited by an equal amount. By forcing the value of the splits to always 'add up' to zero, we can guarantee that the balances of the accounts are always correctly balanced.

The engine does not enforce double-entry accounting, but provides an API to enable user-code to find unbalanced transactions and 'repair' them so that they are in balance.

Note the sum of the values of Splits in a Transaction is always computed with respect to a currency; thus splits can be balanced even when they are in different currencies, as long as they share a common currency. This feature allows currency-trading accounts to be established.

Every Split must point to its parent Transaction, and that Transaction must in turn include that Split in the Transaction's list of Splits. A Split can belong to at most one Transaction. These relationships are enforced by the engine. The engine user cannnot accidentally destroy this relationship as long as they stick to using the API and never access internal structures directly.

Splits are grouped into Accounts which are also known as "Ledgers" in accounting practice. Each Account consists of a list of Splits that debit that Account. To ensure consistency, if a Split points to an Account, then the Account must point to the Split, and vice-versa. A Split can belong to at most one Account. Besides merely containing a list of Splits, the Account structure also gives the Account a name, a code number, description and notes fields, a key-value frame, a pointer to the commodity that is used for all splits in this account. The commodity can be the name of anything traded and tradable: a stock (e.g. "IBM", "McDonald's"), a currency (e.g. "USD", "GBP"), or anything added to the commodity table.

Accounts can be arranged in a hierarchical tree. The nodes of the tree are called "Account Groups". By accounting convention, the value of an Account is equal to the value of all of its Splits plus the value of all of its sub-Accounts.


Define Documentation

#define CREC   'c'

The Split has been cleared

Definition at line 67 of file Split.h.

#define FREC   'f'

frozen into accounting period

Definition at line 69 of file Split.h.

#define NREC   'n'

not reconciled or cleared

Definition at line 70 of file Split.h.

#define SPLIT_ACCOUNT_GUID   "account-guid"

for guid_match_all

Definition at line 502 of file Split.h.

#define TXN_TYPE_INVOICE   'I'

Transaction is an invoice

Definition at line 120 of file Transaction.h.

#define TXN_TYPE_NONE   '\0'

No transaction type

Definition at line 119 of file Transaction.h.

#define TXN_TYPE_PAYMENT   'P'

Transaction is a payment

Definition at line 121 of file Transaction.h.

#define VREC   'v'

split is void

Definition at line 71 of file Split.h.

#define xaccSplitGetGUID (  )     qof_entity_get_guid(QOF_INSTANCE(X))

Deprecated:

Definition at line 510 of file Split.h.

#define xaccSplitReturnGUID (  )     (X ? *(qof_entity_get_guid(QOF_INSTANCE(X))) : *(guid_null()))

Deprecated:

Definition at line 512 of file Split.h.

#define xaccTransAppendSplit ( t,
 )     xaccSplitSetParent((s), (t))

Add a split to the transaction

The xaccTransAppendSplit() method will append the indicated split to the collection of splits in this transaction.

Note:
If the split is already a part of another transaction, it will be removed from that transaction first.

Definition at line 293 of file Transaction.h.

#define xaccTransGetBook (  )     qof_instance_get_book (QOF_INSTANCE(X))

Deprecated:

Definition at line 604 of file Transaction.h.

#define xaccTransGetGUID (  )     qof_entity_get_guid(QOF_INSTANCE(X))

Deprecated:

Definition at line 606 of file Transaction.h.

#define xaccTransGetSlots (  )     qof_instance_get_slots (QOF_INSTANCE(X))

Deprecated:

Definition at line 610 of file Transaction.h.

#define xaccTransReturnGUID (  )     (X ? *(qof_entity_get_guid(QOF_INSTANCE(X))) : *(guid_null()))

Deprecated:

Definition at line 608 of file Transaction.h.

#define xaccTransSetDateSecs   xaccTransSetDatePostedSecs

The xaccTransSetDatePostedSecs() method will modify the posted date of the transaction, specified by a time_t (see ctime(3)). The posted date is the date when this transaction was posted at the bank.

Definition at line 449 of file Transaction.h.

#define YREC   'y'

The Split has been reconciled

Definition at line 68 of file Split.h.


Function Documentation

guint gnc_book_count_transactions ( QofBook book  ) 

Warning:
XXX FIXME gnc_book_count_transactions is a utility function, probably needs to be moved to a utility file somewhere.

Definition at line 1966 of file Transaction.c.

01967 {
01968     guint count = 0;
01969     xaccAccountTreeForEachTransaction(gnc_book_get_root_account(book),
01970                                       counter_thunk, (void*)&count);
01971     return count;
01972 }

gboolean xaccIsPeerSplit ( const Split split_1,
const Split split_2 
)

The xaccIsPeerSplit() is a convenience routine that returns TRUE (a non-zero value) if the two splits share a common parent transaction, else it returns FALSE (zero).

Definition at line 1969 of file Split.c.

01970 {
01971     return (sa && sb && (sa->parent == sb->parent));
01972 }

Split* xaccMallocSplit ( QofBook book  ) 

Constructor.

Definition at line 344 of file Split.c.

00345 {
00346     Split *split;
00347     g_return_val_if_fail (book, NULL);
00348 
00349     split = g_object_new (GNC_TYPE_SPLIT, NULL);
00350     xaccInitSplit (split, book);
00351 
00352     return split;
00353 }

Transaction* xaccMallocTransaction ( QofBook book  ) 

The xaccMallocTransaction() will malloc memory and initialize it. Once created, it is usually unsafe to merely "free" this memory; the xaccTransDestroy() method should be called.

Definition at line 438 of file Transaction.c.

00439 {
00440     Transaction *trans;
00441 
00442     g_return_val_if_fail (book, NULL);
00443 
00444     trans = g_object_new(GNC_TYPE_TRANSACTION, NULL);
00445     xaccInitTransaction (trans, book);
00446     qof_event_gen (&trans->inst, QOF_EVENT_CREATE, NULL);
00447 
00448     return trans;
00449 }

int xaccSplitCompareAccountCodes ( const Split sa,
const Split sb 
)

Compare two splits by code of account. Returns similar to strcmp.

Definition at line 1554 of file Split.c.

01555 {
01556     Account *aa, *ab;
01557     if (!sa && !sb) return 0;
01558     if (!sa) return -1;
01559     if (!sb) return 1;
01560 
01561     aa = sa->acc;
01562     ab = sb->acc;
01563 
01564     return safe_strcmp(xaccAccountGetName(aa), xaccAccountGetName(ab));
01565 }

int xaccSplitCompareAccountFullNames ( const Split sa,
const Split sb 
)

Compare two splits by full name of account. Returns similar to strcmp.

Definition at line 1533 of file Split.c.

01534 {
01535     Account *aa, *ab;
01536     char *full_a, *full_b;
01537     int retval;
01538     if (!sa && !sb) return 0;
01539     if (!sa) return -1;
01540     if (!sb) return 1;
01541 
01542     aa = sa->acc;
01543     ab = sb->acc;
01544     full_a = gnc_account_get_full_name(aa);
01545     full_b = gnc_account_get_full_name(ab);
01546     retval = g_utf8_collate(full_a, full_b);
01547     g_free(full_a);
01548     g_free(full_b);
01549     return retval;
01550 }

int xaccSplitCompareOtherAccountCodes ( const Split sa,
const Split sb 
)

Compare two splits by code of the other account. Returns similar to strcmp. This function attempts to find the split on the other side of a transaction and compare on it.

Definition at line 1589 of file Split.c.

01590 {
01591     const char *ca, *cb;
01592     if (!sa && !sb) return 0;
01593     if (!sa) return -1;
01594     if (!sb) return 1;
01595 
01596     ca = xaccSplitGetCorrAccountCode(sa);
01597     cb = xaccSplitGetCorrAccountCode(sb);
01598     return safe_strcmp(ca, cb);
01599 }

int xaccSplitCompareOtherAccountFullNames ( const Split sa,
const Split sb 
)

Compare two splits by full name of the other account. Returns similar to strcmp. This function attempts to find the split on the other side of a transaction and compare on it.

Definition at line 1568 of file Split.c.

01569 {
01570     char *ca, *cb;
01571     int retval;
01572     if (!sa && !sb) return 0;
01573     if (!sa) return -1;
01574     if (!sb) return 1;
01575 
01576     /* doesn't matter what separator we use
01577      * as long as they are the same
01578      */
01579 
01580     ca = xaccSplitGetCorrAccountFullName(sa);
01581     cb = xaccSplitGetCorrAccountFullName(sb);
01582     retval = safe_strcmp(ca, cb);
01583     g_free(ca);
01584     g_free(cb);
01585     return retval;
01586 }

gboolean xaccSplitDestroy ( Split split  ) 

Destructor.

The xaccSplitDestroy() method will update its parent account and transaction in a consistent manner, resulting in the complete unlinking of the split, and the freeing of its associated memory. The goal of this routine is to perform the removal and destruction of the split in an atomic fashion, with no chance of accidentally leaving the accounting structure out-of-balance or otherwise inconsistent.

If the deletion of the split leaves the transaction with no splits, then the transaction will be marked for deletion. (It will not be deleted until the xaccTransCommitEdit() routine is called.)

Returns:
TRUE upon successful deletion of the split. FALSE when the parenting Transaction is a read-only one.

Definition at line 1335 of file Split.c.

01336 {
01337     Account *acc;
01338     Transaction *trans;
01339     GncEventData ed;
01340 
01341     if (!split) return TRUE;
01342 
01343     acc = split->acc;
01344     trans = split->parent;
01345     if (acc && !qof_instance_get_destroying(acc)
01346             && xaccTransGetReadOnly(trans))
01347         return FALSE;
01348 
01349     xaccTransBeginEdit(trans);
01350     ed.node = split;
01351     ed.idx = xaccTransGetSplitIndex(trans, split);
01352     qof_instance_set_dirty(QOF_INSTANCE(split));
01353     qof_instance_set_destroying(split, TRUE);
01354     qof_event_gen(&trans->inst, GNC_EVENT_ITEM_REMOVED, &ed);
01355     xaccTransCommitEdit(trans);
01356 
01357     return TRUE;
01358 }

gboolean xaccSplitEqual ( const Split sa,
const Split sb,
gboolean  check_guids,
gboolean  check_balances,
gboolean  check_txn_splits 
)

Equality.

Parameters:
sa First split to compare
sb Second split to compare
check_guids If TRUE, try a guid_equal() on the GUIDs of both splits if their pointers are not equal in the first place.
check_balances If TRUE, compare balances between the two splits. Balances are recalculated whenever a split is added or removed from an account, so YMMV on whether this should be set.
check_txn_splits If the pointers are not equal, but everything else so far is equal (including memo, amount, value, kvp_frame), then, when comparing the parenting transactions with xaccTransEqual(), set its argument check_splits to be TRUE.

Definition at line 538 of file Split.c.

00542 {
00543     if (!sa && !sb) return TRUE; /* Arguable. FALSE is better, methinks */
00544 
00545     if (!sa || !sb)
00546     {
00547         PWARN ("one is NULL");
00548         return FALSE;
00549     }
00550 
00551     if (sa == sb) return TRUE;
00552 
00553     if (check_guids)
00554     {
00555         if (qof_instance_guid_compare(sa, sb) != 0)
00556         {
00557             PWARN ("GUIDs differ");
00558             return FALSE;
00559         }
00560     }
00561 
00562     /* Since these strings are cached we can just use pointer equality */
00563     if (sa->memo != sb->memo)
00564     {
00565         PWARN ("memos differ: (%p)%s vs (%p)%s",
00566                sa->memo, sa->memo, sb->memo, sb->memo);
00567         return FALSE;
00568     }
00569 
00570     if (sa->action != sb->action)
00571     {
00572         PWARN ("actions differ: %s vs %s", sa->action, sb->action);
00573         return FALSE;
00574     }
00575 
00576     if (kvp_frame_compare(sa->inst.kvp_data, sb->inst.kvp_data) != 0)
00577     {
00578         char *frame_a;
00579         char *frame_b;
00580 
00581         frame_a = kvp_frame_to_string (sa->inst.kvp_data);
00582         frame_b = kvp_frame_to_string (sb->inst.kvp_data);
00583 
00584         PWARN ("kvp frames differ:\n%s\n\nvs\n\n%s", frame_a, frame_b);
00585 
00586         g_free (frame_a);
00587         g_free (frame_b);
00588 
00589         return FALSE;
00590     }
00591 
00592     if (sa->reconciled != sb->reconciled)
00593     {
00594         PWARN ("reconcile flags differ: %c vs %c", sa->reconciled, sb->reconciled);
00595         return FALSE;
00596     }
00597 
00598     if (timespec_cmp(&(sa->date_reconciled), &(sb->date_reconciled)))
00599     {
00600         PWARN ("reconciled date differs");
00601         return FALSE;
00602     }
00603 
00604     if (!gnc_numeric_eq(xaccSplitGetAmount (sa), xaccSplitGetAmount (sb)))
00605     {
00606         char *str_a;
00607         char *str_b;
00608 
00609         str_a = gnc_numeric_to_string (xaccSplitGetAmount (sa));
00610         str_b = gnc_numeric_to_string (xaccSplitGetAmount (sb));
00611 
00612         PWARN ("amounts differ: %s vs %s", str_a, str_b);
00613 
00614         g_free (str_a);
00615         g_free (str_b);
00616 
00617         return FALSE;
00618     }
00619 
00620     if (!gnc_numeric_eq(xaccSplitGetValue (sa), xaccSplitGetValue (sb)))
00621     {
00622         char *str_a;
00623         char *str_b;
00624 
00625         str_a = gnc_numeric_to_string (xaccSplitGetValue (sa));
00626         str_b = gnc_numeric_to_string (xaccSplitGetValue (sb));
00627 
00628         PWARN ("values differ: %s vs %s", str_a, str_b);
00629 
00630         g_free (str_a);
00631         g_free (str_b);
00632 
00633         return FALSE;
00634     }
00635 
00636     if (check_balances)
00637     {
00638         if (!xaccSplitEqualCheckBal ("", sa->balance, sb->balance))
00639             return FALSE;
00640         if (!xaccSplitEqualCheckBal ("cleared ", sa->cleared_balance,
00641                                      sb->cleared_balance))
00642             return FALSE;
00643         if (!xaccSplitEqualCheckBal ("reconciled ", sa->reconciled_balance,
00644                                      sb->reconciled_balance))
00645             return FALSE;
00646     }
00647 
00648     if (!xaccTransEqual(sa->parent, sb->parent, check_guids, check_txn_splits,
00649                         check_balances, FALSE))
00650     {
00651         PWARN ("transactions differ");
00652         return FALSE;
00653     }
00654 
00655     return TRUE;
00656 }

Account* xaccSplitGetAccount ( const Split split  ) 

Returns the account of this split, which was set through xaccAccountInsertSplit().

Definition at line 686 of file Split.c.

00687 {
00688     return s ? s->acc : NULL;
00689 }

const char* xaccSplitGetAction ( const Split split  ) 

Returns the action string.

Definition at line 1799 of file Split.c.

01800 {
01801     return split ? split->action : NULL;
01802 }

gnc_numeric xaccSplitGetAmount ( const Split split  ) 

Returns the amount of the split in the account's commodity. Note that for cap-gains splits, this is slaved to the transaction that is causing the gains to occur.

Definition at line 1812 of file Split.c.

01813 {
01814     return split ? split->amount : gnc_numeric_zero();
01815 }

gnc_numeric xaccSplitGetBalance ( const Split split  ) 

Returns the running balance up to and including the indicated split. The balance is the currency-denominated balance. For accounts with non-unit share prices, it is correctly adjusted for share prices.

Returns the running balance up to & including the indicated split.

Definition at line 1105 of file Split.c.

01106 {
01107     return s ? s->balance : gnc_numeric_zero();
01108 }

gnc_numeric xaccSplitGetBaseValue ( const Split split,
const gnc_commodity base_currency 
)

Depending on the base_currency, return either the value or the amount of this split: If the base_curreny is the transaction's commodity, return the value. If it is the account's commodity, return the amount. If it is neither print a warning message and return gnc_numeric_zero().

Definition at line 1178 of file Split.c.

01179 {
01180     if (!s || !s->acc || !s->parent) return gnc_numeric_zero();
01181 
01182     /* be more precise -- the value depends on the currency we want it
01183      * expressed in.  */
01184     if (gnc_commodity_equiv(xaccTransGetCurrency(s->parent), base_currency))
01185         return xaccSplitGetValue(s);
01186     if (gnc_commodity_equiv(xaccAccountGetCommodity(s->acc), base_currency))
01187         return xaccSplitGetAmount(s);
01188 
01189     PERR ("inappropriate base currency %s "
01190           "given split currency=%s and commodity=%s\n",
01191           gnc_commodity_get_printname(base_currency),
01192           gnc_commodity_get_printname(xaccTransGetCurrency (s->parent)),
01193           gnc_commodity_get_printname(xaccAccountGetCommodity(s->acc)));
01194     return gnc_numeric_zero();
01195 }

QofBook* xaccSplitGetBook ( const Split split  ) 

Returns the book of this split, i.e. the entity where this split is stored.

Definition at line 1867 of file Split.c.

01868 {
01869     return qof_instance_get_book(QOF_INSTANCE(split));
01870 }

gnc_numeric xaccSplitGetClearedBalance ( const Split split  ) 

The cleared-balance is the currency-denominated balance of all transactions that have been marked as cleared or reconciled. It is correctly adjusted for price fluctuations.

Returns the running balance up to & including the indicated split.

Definition at line 1111 of file Split.c.

01112 {
01113     return s ? s->cleared_balance : gnc_numeric_zero();
01114 }

const char* xaccSplitGetCorrAccountCode ( const Split sa  ) 

document me

Definition at line 1515 of file Split.c.

01516 {
01517     static const char *split_const = NULL;
01518     const Split *other_split;
01519 
01520     if (!get_corr_account_split(sa, &other_split))
01521     {
01522         if (!split_const)
01523             /* Translators: This string has a disambiguation prefix */
01524             split_const = Q_("Displayed account code of the other account in a multi-split transaction|Split");
01525 
01526         return split_const;
01527     }
01528     return xaccAccountGetCode(other_split->acc);
01529 }

char* xaccSplitGetCorrAccountFullName ( const Split sa  ) 

These functions take a split, get the corresponding split on the "other side" of the transaction, and extract either the name or code of that split, reverting to returning a constant "Split" if the transaction has more than one split on the "other side". These were added for the transaction report, and is in C because the code was already written in C for the above functions and duplication is silly.

Definition at line 1499 of file Split.c.

01500 {
01501     static const char *split_const = NULL;
01502     const Split *other_split;
01503 
01504     if (!get_corr_account_split(sa, &other_split))
01505     {
01506         if (!split_const)
01507             split_const = _("-- Split Transaction --");
01508 
01509         return g_strdup(split_const);
01510     }
01511     return gnc_account_get_full_name(other_split->acc);
01512 }

const char* xaccSplitGetCorrAccountName ( const Split sa  ) 

document me

Definition at line 1482 of file Split.c.

01483 {
01484     static const char *split_const = NULL;
01485     const Split *other_split;
01486 
01487     if (!get_corr_account_split(sa, &other_split))
01488     {
01489         if (!split_const)
01490             split_const = _("-- Split Transaction --");
01491 
01492         return split_const;
01493     }
01494 
01495     return xaccAccountGetName(other_split->acc);
01496 }

void xaccSplitGetDateReconciledTS ( const Split split,
Timespec ts 
)

Get the date on which this split was reconciled by having it written into the Timespec that 'ts' is pointing to.

Definition at line 1710 of file Split.c.

01711 {
01712     if (!split || !ts) return;
01713     *ts = (split->date_reconciled);
01714 }

GNCLot* xaccSplitGetLot ( const Split split  ) 

Returns the pointer to the debited/credited Lot where this split belongs to, or NULL if it doesn't belong to any.

Definition at line 1778 of file Split.c.

01779 {
01780     return split ? split->lot : NULL;
01781 }

const char* xaccSplitGetMemo ( const Split split  ) 

Returns the memo string.

Definition at line 1793 of file Split.c.

01794 {
01795     return split ? split->memo : NULL;
01796 }

Split* xaccSplitGetOtherSplit ( const Split split  ) 

The xaccSplitGetOtherSplit() is a convenience routine that returns the other of a pair of splits. If there are more than two splits, it returns NULL.

Definition at line 1911 of file Split.c.

01912 {
01913     int i;
01914     Transaction *trans;
01915     int count, num_splits;
01916     Split *other = NULL;
01917     KvpValue *sva;
01918     gboolean trading_accts;
01919 
01920     if (!split) return NULL;
01921     trans = split->parent;
01922     if (!trans) return NULL;
01923 
01924 #ifdef OLD_ALGO_HAS_ONLY_TWO_SPLITS
01925     Split *s1, *s2;
01926     if (g_list_length (trans->splits) != 2) return NULL;
01927 
01928     s1 = g_list_nth_data (trans->splits, 0);
01929     s2 = g_list_nth_data (trans->splits, 1);
01930 
01931     if (s1 == split) return s2;
01932     return s1;
01933 #endif
01934 
01935     trading_accts = xaccTransUseTradingAccounts (trans);
01936     num_splits = xaccTransCountSplits(trans);
01937     count = num_splits;
01938     sva = kvp_frame_get_slot (split->inst.kvp_data, "lot-split");
01939     if (!sva && !trading_accts && (2 != count)) return NULL;
01940 
01941     for (i = 0; i < num_splits; i++)
01942     {
01943         Split *s = xaccTransGetSplit(trans, i);
01944         if (s == split)
01945         {
01946             --count;
01947             continue;
01948         }
01949         if (kvp_frame_get_slot (s->inst.kvp_data, "lot-split"))
01950         {
01951             --count;
01952             continue;
01953         }
01954         if (trading_accts &&
01955                 xaccAccountGetType(xaccSplitGetAccount(s)) == ACCT_TYPE_TRADING)
01956         {
01957             --count;
01958             continue;
01959         }
01960         other = s;
01961     }
01962     return (1 == count) ? other : NULL;
01963 }

Transaction* xaccSplitGetParent ( const Split split  ) 

Returns the parent transaction of the split.

Definition at line 1728 of file Split.c.

01729 {
01730     return split ? split->parent : NULL;
01731 }

char xaccSplitGetReconcile ( const Split split  ) 

Returns the value of the reconcile flag.

Definition at line 1805 of file Split.c.

01806 {
01807     return split ? split->reconciled : ' ';
01808 }

gnc_numeric xaccSplitGetReconciledBalance ( const Split split  ) 

Returns the reconciled-balance of this split. The reconciled-balance is the currency-denominated balance of all transactions that have been marked as reconciled.

Returns the running balance up to & including the indicated split.

Definition at line 1117 of file Split.c.

01118 {
01119     return s ? s->reconciled_balance : gnc_numeric_zero();
01120 }

gnc_numeric xaccSplitGetSharePrice ( const Split split  ) 

Returns the price of the split, that is, the value divided by the amount. If the amount is zero, returns a gnc_numeric of value one.

Definition at line 1824 of file Split.c.

01825 {
01826     gnc_numeric amt, val, price;
01827     if (!split) return gnc_numeric_create(1, 1);
01828 
01829 
01830     /* if amount == 0 and value == 0, then return 1.
01831      * if amount == 0 and value != 0 then return 0.
01832      * otherwise return value/amount
01833      */
01834 
01835     amt = xaccSplitGetAmount(split);
01836     val = xaccSplitGetValue(split);
01837     if (gnc_numeric_zero_p(amt))
01838     {
01839         if (gnc_numeric_zero_p(val))
01840             return gnc_numeric_create(1, 1);
01841         return gnc_numeric_create(0, 1);
01842     }
01843     price = gnc_numeric_div(val, amt,
01844                             GNC_DENOM_AUTO,
01845                             GNC_HOW_DENOM_SIGFIGS(PRICE_SIGFIGS) |
01846                             GNC_HOW_RND_ROUND);
01847 
01848     /* During random checks we can get some very weird prices.  Let's
01849      * handle some overflow and other error conditions by returning
01850      * zero.  But still print an error to let us know it happened.
01851      */
01852     if (gnc_numeric_check(price))
01853     {
01854         PERR("Computing share price failed (%d): [ %" G_GINT64_FORMAT " / %"
01855              G_GINT64_FORMAT " ] / [ %" G_GINT64_FORMAT " / %" G_GINT64_FORMAT " ]",
01856              gnc_numeric_check(price), val.num, val.denom, amt.num, amt.denom);
01857         return gnc_numeric_create(0, 1);
01858     }
01859 
01860     return price;
01861 }

KvpFrame* xaccSplitGetSlots ( const Split split  ) 

Returns the KvpFrame slots of this split for direct editing.

Split slots are used to store arbitrary strings, numbers, and structures which aren't members of the transaction struct. See kvp_doc.txt for reserved slot names.

Definition at line 910 of file Split.c.

00911 {
00912     return qof_instance_get_slots(QOF_INSTANCE(s));
00913 }

const char* xaccSplitGetType ( const Split s  ) 

Returns the split type, which is either the string "normal", or "stock-split" for a split from a stock split (pun intended? :-).

Definition at line 1873 of file Split.c.

01874 {
01875     const char *split_type;
01876 
01877     if (!s) return NULL;
01878     split_type = kvp_frame_get_string(s->inst.kvp_data, "split-type");
01879     return split_type ? split_type : "normal";
01880 }

gnc_numeric xaccSplitGetValue ( const Split split  ) 

Returns the value of this split in the transaction's commodity. Note that for cap-gains splits, this is slaved to the transaction that is causing the gains to occur.

Definition at line 1818 of file Split.c.

01819 {
01820     return split ? split->value : gnc_numeric_zero();
01821 }

Split* xaccSplitLookup ( const GUID *  guid,
QofBook book 
)

The xaccSplitLookup() subroutine will return the split associated with the given id, or NULL if there is no such split.

Definition at line 817 of file Split.c.

00818 {
00819     QofCollection *col;
00820     if (!guid || !book) return NULL;
00821     col = qof_book_get_collection (book, GNC_ID_SPLIT);
00822     return (Split *) qof_collection_lookup_entity (col, guid);
00823 }

void xaccSplitMakeStockSplit ( Split s  ) 

Mark a split to be of type stock split - after this, you shouldn't modify the value anymore, just the amount.

Definition at line 1885 of file Split.c.

01886 {
01887     xaccTransBeginEdit (s->parent);
01888 
01889     s->value = gnc_numeric_zero();
01890     kvp_frame_set_str(s->inst.kvp_data, "split-type", "stock-split");
01891     SET_GAINS_VDIRTY(s);
01892     mark_split(s);
01893     qof_instance_set_dirty(QOF_INSTANCE(s));
01894     xaccTransCommitEdit(s->parent);
01895 }

gint xaccSplitOrder ( const Split sa,
const Split sb 
)

The xaccSplitOrder(sa,sb) method is useful for sorting. if sa and sb have different transactions, return their xaccTransOrder return a negative value if split sa has a smaller currency-value than sb, return a positive value if split sa has a larger currency-value than sb, return a negative value if split sa has a smaller share-price than sb, return a positive value if split sa has a larger share-price than sb, then compares memo and action using the strcmp() c-library routine, returning what strcmp would return. Then it compares the reconciled flags, then the reconciled dates, Finally, it returns zero if all of the above match.

Definition at line 1364 of file Split.c.

01365 {
01366     int retval;
01367     int comp;
01368     char *da, *db;
01369 
01370     if (sa == sb) return 0;
01371     /* nothing is always less than something */
01372     if (!sa && sb) return -1;
01373     if (sa && !sb) return +1;
01374 
01375     retval = xaccTransOrder (sa->parent, sb->parent);
01376     if (retval) return retval;
01377 
01378     /* otherwise, sort on memo strings */
01379     da = sa->memo ? sa->memo : "";
01380     db = sb->memo ? sb->memo : "";
01381     retval = g_utf8_collate (da, db);
01382     if (retval)
01383         return retval;
01384 
01385     /* otherwise, sort on action strings */
01386     da = sa->action ? sa->action : "";
01387     db = sb->action ? sb->action : "";
01388     retval = g_utf8_collate (da, db);
01389     if (retval != 0)
01390         return retval;
01391 
01392     /* the reconciled flag ... */
01393     if (sa->reconciled < sb->reconciled) return -1;
01394     if (sa->reconciled > sb->reconciled) return +1;
01395 
01396     /* compare amounts */
01397     comp = gnc_numeric_compare(xaccSplitGetAmount(sa), xaccSplitGetAmount (sb));
01398     if (comp < 0) return -1;
01399     if (comp > 0) return +1;
01400 
01401     comp = gnc_numeric_compare(xaccSplitGetValue(sa), xaccSplitGetValue (sb));
01402     if (comp < 0) return -1;
01403     if (comp > 0) return +1;
01404 
01405     /* if dates differ, return */
01406     DATE_CMP(sa, sb, date_reconciled);
01407 
01408     /* else, sort on guid - keeps sort stable. */
01409     retval = qof_instance_guid_compare(sa, sb);
01410     if (retval) return retval;
01411 
01412     return 0;
01413 }

Timespec xaccSplitRetDateReconciledTS ( const Split split  ) 

Returns the date (as Timespec) on which this split was reconciled.

Definition at line 1717 of file Split.c.

01718 {
01719     Timespec ts = {0, 0};
01720     return split ? split->date_reconciled : ts;
01721 }

void xaccSplitSetAction ( Split split,
const char *  action 
)

The Action is an arbitrary user-assigned string. The action field is an arbitrary user-assigned value. It is meant to be a very short (one to ten character) string that signifies the "type" of this split, such as e.g. Buy, Sell, Div, Withdraw, Deposit, ATM, Check, etc. The idea is that this field can be used to create custom reports or graphs of data.

Definition at line 1628 of file Split.c.

01629 {
01630     if (!split || !actn) return;
01631     xaccTransBeginEdit (split->parent);
01632 
01633     CACHE_REPLACE(split->action, actn);
01634     qof_instance_set_dirty(QOF_INSTANCE(split));
01635     xaccTransCommitEdit(split->parent);
01636 
01637 }

void xaccSplitSetAmount ( Split split,
gnc_numeric  amount 
)

The xaccSplitSetAmount() method sets the amount in the account's commodity that the split should have.

The following four setter functions set the prices and amounts. All of the routines always maintain balance: that is, invoking any of them will cause other splits in the transaction to be modified so that the net value of the transaction is zero.

IMPORTANT: The split should be parented by an account before any of these routines are invoked! This is because the actual setting of amounts/values requires SCU settings from the account. If these are not available, then amounts/values will be set to -1/0, which is an invalid value. I believe this order dependency is a bug, but I'm too lazy to find, fix & test at the moment ...

Note:
If you use this on a newly created transaction, make sure that the 'value' is also set so that it doesn't remain zero.

Definition at line 1045 of file Split.c.

01046 {
01047     if (!s) return;
01048     g_return_if_fail(gnc_numeric_check(amt) == GNC_ERROR_OK);
01049     ENTER ("(split=%p) old amt=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT
01050            " new amt=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, s,
01051            s->amount.num, s->amount.denom, amt.num, amt.denom);
01052 
01053     xaccTransBeginEdit (s->parent);
01054     if (s->acc)
01055         s->amount = gnc_numeric_convert(amt, get_commodity_denom(s),
01056                                         GNC_HOW_RND_ROUND);
01057     else
01058         s->amount = amt;
01059 
01060     SET_GAINS_ADIRTY(s);
01061     mark_split (s);
01062     qof_instance_set_dirty(QOF_INSTANCE(s));
01063     xaccTransCommitEdit(s->parent);
01064     LEAVE("");
01065 }

void xaccSplitSetBaseValue ( Split split,
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_currency is the transaction's commodity, set the value. If it is the account's commodity, set the amount. If both, set both.

Note:
WATCH OUT: When using this function and the transaction's and account's commodities are different, the amount or the value will be left as zero. This might screw up the multi-currency handling code in the register. So please think twice whether you need this function -- using xaccSplitSetValue() together with xaccSplitSetAmount() is definitely the better and safer solution!

Definition at line 1123 of file Split.c.

01125 {
01126     const gnc_commodity *currency;
01127     const gnc_commodity *commodity;
01128 
01129     if (!s) return;
01130     xaccTransBeginEdit (s->parent);
01131 
01132     if (!s->acc)
01133     {
01134         PERR ("split must have a parent account");
01135         return;
01136     }
01137 
01138     currency = xaccTransGetCurrency (s->parent);
01139     commodity = xaccAccountGetCommodity (s->acc);
01140 
01141     /* If the base_currency is the transaction's commodity ('currency'),
01142      * set the value.  If it's the account commodity, set the
01143      * amount. If both, set both. */
01144     if (gnc_commodity_equiv(currency, base_currency))
01145     {
01146         if (gnc_commodity_equiv(commodity, base_currency))
01147         {
01148             s->amount = gnc_numeric_convert(value,
01149                                             get_commodity_denom(s),
01150                                             GNC_HOW_RND_ROUND);
01151         }
01152         s->value = gnc_numeric_convert(value,
01153                                        get_currency_denom(s),
01154                                        GNC_HOW_RND_ROUND);
01155     }
01156     else if (gnc_commodity_equiv(commodity, base_currency))
01157     {
01158         s->amount = gnc_numeric_convert(value, get_commodity_denom(s),
01159                                         GNC_HOW_RND_ROUND);
01160     }
01161     else
01162     {
01163         PERR ("inappropriate base currency %s "
01164               "given split currency=%s and commodity=%s\n",
01165               gnc_commodity_get_printname(base_currency),
01166               gnc_commodity_get_printname(currency),
01167               gnc_commodity_get_printname(commodity));
01168         return;
01169     }
01170 
01171     SET_GAINS_A_VDIRTY(s);
01172     mark_split (s);
01173     qof_instance_set_dirty(QOF_INSTANCE(s));
01174     xaccTransCommitEdit(s->parent);
01175 }

void xaccSplitSetDateReconciledSecs ( Split split,
time_t  time 
)

Set the date on which this split was reconciled by specifying the time as time_t.

Definition at line 1685 of file Split.c.

01686 {
01687     if (!split) return;
01688     xaccTransBeginEdit (split->parent);
01689 
01690     split->date_reconciled.tv_sec = secs;
01691     split->date_reconciled.tv_nsec = 0;
01692     qof_instance_set_dirty(QOF_INSTANCE(split));
01693     xaccTransCommitEdit(split->parent);
01694 
01695 }

void xaccSplitSetDateReconciledTS ( Split split,
Timespec ts 
)

Set the date on which this split was reconciled by specifying the time as Timespec. Caller still owns *ts!

Definition at line 1698 of file Split.c.

01699 {
01700     if (!split || !ts) return;
01701     xaccTransBeginEdit (split->parent);
01702 
01703     split->date_reconciled = *ts;
01704     qof_instance_set_dirty(QOF_INSTANCE(split));
01705     xaccTransCommitEdit(split->parent);
01706 
01707 }

void xaccSplitSetLot ( Split split,
GNCLot lot 
)

Assigns the split to a specific Lot

Definition at line 1784 of file Split.c.

01785 {
01786     xaccTransBeginEdit (split->parent);
01787     split->lot = lot;
01788     qof_instance_set_dirty(QOF_INSTANCE(split));
01789     xaccTransCommitEdit(split->parent);
01790 }

void xaccSplitSetMemo ( Split split,
const char *  memo 
)

The memo is an arbitrary string associated with a split. It is intended to hold a short (zero to forty character) string that is displayed by the GUI along with this split. Users typically type in free form text from the GUI.

Definition at line 1609 of file Split.c.

01610 {
01611     if (!split || !memo) return;
01612     xaccTransBeginEdit (split->parent);
01613 
01614     CACHE_REPLACE(split->memo, memo);
01615     qof_instance_set_dirty(QOF_INSTANCE(split));
01616     xaccTransCommitEdit(split->parent);
01617 
01618 }

void xaccSplitSetReconcile ( Split split,
char  reconciled_flag 
)

Set the reconcile flag. The Reconcile flag is a single char, whose values are typically are 'n', 'y', 'c'. In Transaction.h, macros are defined for typical values (e.g. CREC, YREC).

Definition at line 1660 of file Split.c.

01661 {
01662     if (!split || split->reconciled == recn) return;
01663     xaccTransBeginEdit (split->parent);
01664 
01665     switch (recn)
01666     {
01667     case NREC:
01668     case CREC:
01669     case YREC:
01670     case FREC:
01671     case VREC:
01672         split->reconciled = recn;
01673         mark_split (split);
01674         qof_instance_set_dirty(QOF_INSTANCE(split));
01675         xaccAccountRecomputeBalance (split->acc);
01676         break;
01677     default:
01678         PERR("Bad reconciled flag");
01679     }
01680     xaccTransCommitEdit(split->parent);
01681 
01682 }

void xaccSplitSetSharePrice ( Split split,
gnc_numeric  price 
)

Deprecated:
The xaccSplitSetSharePrice() method sets the price of the split. DEPRECATED - set the value and amount instead.

Definition at line 976 of file Split.c.

00977 {
00978     if (!s) return;
00979     ENTER (" ");
00980     xaccTransBeginEdit (s->parent);
00981 
00982     s->value = gnc_numeric_mul(xaccSplitGetAmount(s),
00983                                price, get_currency_denom(s),
00984                                GNC_HOW_RND_ROUND);
00985 
00986     SET_GAINS_VDIRTY(s);
00987     mark_split (s);
00988     qof_instance_set_dirty(QOF_INSTANCE(s));
00989     xaccTransCommitEdit(s->parent);
00990     LEAVE ("");
00991 }

void xaccSplitSetSharePriceAndAmount ( Split split,
gnc_numeric  price,
gnc_numeric  amount 
)

The xaccSplitSetSharePriceAndAmount() method will simultaneously update the share price and the number of shares. This is a utility routine that is equivalent to a xaccSplitSetSharePrice() followed by and xaccSplitSetAmount(), except that it incurs the processing overhead of balancing only once, instead of twice.

Definition at line 948 of file Split.c.

00949 {
00950     if (!s) return;
00951     ENTER (" ");
00952     xaccTransBeginEdit (s->parent);
00953 
00954     s->amount = gnc_numeric_convert(amt, get_commodity_denom(s),
00955                                     GNC_HOW_RND_ROUND);
00956     s->value  = gnc_numeric_mul(s->amount, price,
00957                                 get_currency_denom(s), GNC_HOW_RND_ROUND);
00958 
00959     SET_GAINS_A_VDIRTY(s);
00960     mark_split (s);
00961     qof_instance_set_dirty(QOF_INSTANCE(s));
00962     xaccTransCommitEdit(s->parent);
00963     LEAVE ("");
00964 }

void xaccSplitSetSlots_nc ( Split s,
KvpFrame frm 
)

Set the KvpFrame slots of this split to the given frm by directly using the frm pointer (i.e. non-copying).

Definition at line 916 of file Split.c.

00917 {
00918     if (!s || !frm) return;
00919     xaccTransBeginEdit(s->parent);
00920     qof_instance_set_slots(QOF_INSTANCE(s), frm);
00921     xaccTransCommitEdit(s->parent);
00922 
00923 }

void xaccSplitSetValue ( Split split,
gnc_numeric  value 
)

The xaccSplitSetValue() method sets the value of this split in the transaction's commodity.

Note:
If you use this on a newly created transaction, make sure that the 'amount' is also set so that it doesn't remain zero.

Definition at line 1077 of file Split.c.

01078 {
01079     gnc_numeric new_val;
01080     if (!s) return;
01081 
01082     g_return_if_fail(gnc_numeric_check(amt) == GNC_ERROR_OK);
01083     ENTER ("(split=%p) old val=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT
01084            " new val=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, s,
01085            s->value.num, s->value.denom, amt.num, amt.denom);
01086 
01087     xaccTransBeginEdit (s->parent);
01088     new_val = gnc_numeric_convert(amt, get_currency_denom(s),
01089                                   GNC_HOW_RND_ROUND);
01090     if (gnc_numeric_check(new_val) == GNC_ERROR_OK)
01091         s->value = new_val;
01092     else PERR("numeric error in converting the split value's denominator");
01093 
01094     SET_GAINS_VDIRTY(s);
01095     mark_split (s);
01096     qof_instance_set_dirty(QOF_INSTANCE(s));
01097     xaccTransCommitEdit(s->parent);
01098     LEAVE ("");
01099 }

gnc_numeric xaccSplitVoidFormerAmount ( const Split split  ) 

Returns the original pre-void amount of a split.

Parameters:
split The split in question.
Returns:
A gnc_numeric containing the original value of this split. Returns a gnc_numeric of zero upon error.

Definition at line 1975 of file Split.c.

01976 {
01977     g_return_val_if_fail(split, gnc_numeric_zero());
01978     return kvp_frame_get_numeric(split->inst.kvp_data, void_former_amt_str);
01979 }

gnc_numeric xaccSplitVoidFormerValue ( const Split split  ) 

Returns the original pre-void value of a split.

Parameters:
split The split in question.
Returns:
A gnc_numeric containing the original amount of this split. Returns a gnc_numeric of zero upon error.

Definition at line 1982 of file Split.c.

01983 {
01984     g_return_val_if_fail(split, gnc_numeric_zero());
01985     return kvp_frame_get_numeric(split->inst.kvp_data, void_former_val_str);
01986 }

void xaccTransBeginEdit ( Transaction trans  ) 

The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of its component splits. If this is not done, errors will result.

Definition at line 1101 of file Transaction.c.

01102 {
01103     if (!trans) return;
01104     if (!qof_begin_edit(&trans->inst)) return;
01105 
01106     if (qof_book_shutting_down(qof_instance_get_book(trans))) return;
01107 
01108     xaccOpenLog ();
01109     xaccTransWriteLog (trans, 'B');
01110 
01111     /* Make a clone of the transaction; we will use this
01112      * in case we need to roll-back the edit. */
01113     trans->orig = xaccDupeTransaction (trans);
01114 }

Transaction* xaccTransClone ( const Transaction t  ) 

The xaccTransClone() method will create a complete copy of an existing transaction.

Definition at line 563 of file Transaction.c.

00564 {
00565     Transaction *to;
00566     Split *split;
00567     GList *node;
00568 
00569     qof_event_suspend();
00570     to = g_object_new (GNC_TYPE_TRANSACTION, NULL);
00571 
00572     to->date_entered    = from->date_entered;
00573     to->date_posted     = from->date_posted;
00574     to->num             = CACHE_INSERT (from->num);
00575     to->description     = CACHE_INSERT (from->description);
00576     to->common_currency = from->common_currency;
00577     qof_instance_copy_version(to, from);
00578     qof_instance_copy_version_check(to, from);
00579 
00580     to->orig            = NULL;
00581 
00582     qof_instance_init_data (&to->inst, GNC_ID_TRANS, qof_instance_get_book(from));
00583     kvp_frame_delete (to->inst.kvp_data);
00584     to->inst.kvp_data    = kvp_frame_copy (from->inst.kvp_data);
00585 
00586     xaccTransBeginEdit(to);
00587     for (node = from->splits; node; node = node->next)
00588     {
00589         split = xaccSplitClone(node->data);
00590         split->parent = to;
00591         to->splits = g_list_append (to->splits, split);
00592     }
00593     qof_instance_set_dirty(QOF_INSTANCE(to));
00594     xaccTransCommitEdit(to);
00595     qof_event_resume();
00596 
00597     return to;
00598 }

void xaccTransCommitEdit ( Transaction trans  ) 

The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are complete and should be made permanent. Note this routine may result in the deletion of the transaction, if the transaction is "empty" (has no splits), or of xaccTransDestroy() was called on the transaction.

Definition at line 1282 of file Transaction.c.

01283 {
01284     if (!trans) return;
01285     ENTER ("(trans=%p)", trans);
01286 
01287     if (!qof_commit_edit (QOF_INSTANCE(trans)))
01288     {
01289         LEAVE("editlevel non-zero");
01290         return;
01291     }
01292 
01293     /* We increment this for the duration of the call
01294      * so other functions don't result in a recursive
01295      * call to xaccTransCommitEdit. */
01296     qof_instance_increase_editlevel(trans);
01297 
01298     if (was_trans_emptied(trans))
01299         qof_instance_set_destroying(trans, TRUE);
01300 
01301     /* Before commiting the transaction, we're gonna enforce certain
01302      * constraints.  In particular, we want to enforce the cap-gains
01303      * and the balanced lot constraints.  These constraints might
01304      * change the number of splits in this transaction, and the
01305      * transaction itself might be deleted.  This is also why
01306      * we can't really enforce these constraints elsewhere: they
01307      * can cause pointers to splits and transactions to disapear out
01308      * from under the holder.
01309      */
01310     if (!qof_instance_get_destroying(trans) && scrub_data &&
01311             !qof_book_shutting_down(xaccTransGetBook(trans)))
01312     {
01313         /* If scrubbing gains recurses through here, don't call it again. */
01314         scrub_data = 0;
01315         /* The total value of the transaction should sum to zero.
01316          * Call the trans scrub routine to fix it.   Indirectly, this
01317          * routine also performs a number of other transaction fixes too.
01318          */
01319         xaccTransScrubImbalance (trans, NULL, NULL);
01320         /* Get the cap gains into a consistent state as well. */
01321 
01322         /* Lot Scrubbing is temporarily disabled. */
01323         if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
01324             xaccTransScrubGains (trans, NULL);
01325 
01326         /* Allow scrubbing in transaction commit again */
01327         scrub_data = 1;
01328     }
01329 
01330     /* Record the time of last modification */
01331     if (0 == trans->date_entered.tv_sec)
01332     {
01333         struct timeval tv;
01334 #ifdef HAVE_GETTIMEOFDAY
01335         gettimeofday (&tv, NULL);
01336 #else
01337         time (&(tv.tv_sec));
01338         tv.tv_usec = 0;
01339 #endif
01340         trans->date_entered.tv_sec = tv.tv_sec;
01341         trans->date_entered.tv_nsec = 1000 * tv.tv_usec;
01342         qof_instance_set_dirty(QOF_INSTANCE(trans));
01343     }
01344 
01345     qof_commit_edit_part2(QOF_INSTANCE(trans),
01346                           (void (*) (QofInstance *, QofBackendError))
01347                           trans_on_error,
01348                           (void (*) (QofInstance *)) trans_cleanup_commit,
01349                           (void (*) (QofInstance *)) do_destroy);
01350     LEAVE ("(trans=%p)", trans);
01351 }

int xaccTransCountSplits ( const Transaction trans  ) 

Returns the number of splits in this transaction.

Definition at line 1780 of file Transaction.c.

01781 {
01782     gint i = 0;
01783     FOR_EACH_SPLIT(trans, i++);
01784     return i;
01785 }

void xaccTransDestroy ( Transaction trans  ) 

Destroys a transaction. Each split in transaction trans is removed from its account and destroyed as well.

If the transaction has not already been opened for editing with xaccTransBeginEdit() then the changes are committed immediately. Otherwise, the caller must follow up with either xaccTransCommitEdit(), in which case the transaction and split memory will be freed, or xaccTransRollbackEdit(), in which case nothing at all is freed, and everything is put back into original order.

Parameters:
trans the transaction to destroy

Definition at line 1120 of file Transaction.c.

01121 {
01122     if (!trans) return;
01123 
01124     if (!xaccTransGetReadOnly (trans) ||
01125             qof_book_shutting_down(qof_instance_get_book(trans)))
01126     {
01127         xaccTransBeginEdit(trans);
01128         qof_instance_set_destroying(trans, TRUE);
01129         xaccTransCommitEdit(trans);
01130     }
01131 }

gboolean xaccTransEqual ( const Transaction ta,
const Transaction tb,
gboolean  check_guids,
gboolean  check_splits,
gboolean  check_balances,
gboolean  assume_ordered 
)

Equality.

Parameters:
ta First transaction to compare
tb Second transaction to compare
check_guids If TRUE, try a guid_equal() on the GUIDs of both transactions if their pointers are not equal in the first place. Also passed to subsidiary calls to xaccSplitEqual.
check_splits If TRUE, after checking the transaction data structures for equality, also check all splits attached to the transation for equality.
check_balances If TRUE, when checking splits also compare balances between the two splits. Balances are recalculated whenever a split is added or removed from an account, so YMMV on whether this should be set.
assume_ordered If TRUE, assume that the splits in each transaction appear in the same order. This saves some time looking up splits by GUID, and is required for checking duplicated transactions because all the splits have new GUIDs.

Definition at line 674 of file Transaction.c.

00679 {
00680     if (!ta && !tb) return TRUE; /* Arguable.  FALSE may be better. */
00681 
00682     if (!ta || !tb)
00683     {
00684         PWARN ("one is NULL");
00685         return FALSE;
00686     }
00687 
00688     if (ta == tb) return TRUE;
00689 
00690     if (check_guids)
00691     {
00692         if (qof_instance_guid_compare(ta, tb) != 0)
00693         {
00694             PWARN ("GUIDs differ");
00695             return FALSE;
00696         }
00697     }
00698 
00699     if (!gnc_commodity_equal(ta->common_currency, tb->common_currency))
00700     {
00701         PWARN ("commodities differ %s vs %s",
00702                gnc_commodity_get_unique_name (ta->common_currency),
00703                gnc_commodity_get_unique_name (tb->common_currency));
00704         return FALSE;
00705     }
00706 
00707     if (timespec_cmp(&(ta->date_entered), &(tb->date_entered)))
00708     {
00709         PWARN ("date entered differs");
00710         return FALSE;
00711     }
00712 
00713     if (timespec_cmp(&(ta->date_posted), &(tb->date_posted)))
00714     {
00715         PWARN ("date posted differs");
00716         return FALSE;
00717     }
00718 
00719     /* Since we use cached strings, we can just compare pointer
00720      * equality for num and description
00721      */
00722     if (ta->num != tb->num)
00723     {
00724         PWARN ("num differs: %s vs %s", ta->num, tb->num);
00725         return FALSE;
00726     }
00727 
00728     if (ta->description != tb->description)
00729     {
00730         PWARN ("descriptions differ: %s vs %s", ta->description, tb->description);
00731         return FALSE;
00732     }
00733 
00734     if (kvp_frame_compare(ta->inst.kvp_data, tb->inst.kvp_data) != 0)
00735     {
00736         char *frame_a;
00737         char *frame_b;
00738 
00739         frame_a = kvp_frame_to_string (ta->inst.kvp_data);
00740         frame_b = kvp_frame_to_string (tb->inst.kvp_data);
00741 
00742         PWARN ("kvp frames differ:\n%s\n\nvs\n\n%s", frame_a, frame_b);
00743 
00744         g_free (frame_a);
00745         g_free (frame_b);
00746 
00747         return FALSE;
00748     }
00749 
00750     if (check_splits)
00751     {
00752         if ((!ta->splits && tb->splits) || (!tb->splits && ta->splits))
00753         {
00754             PWARN ("only one has splits");
00755             return FALSE;
00756         }
00757 
00758         if (ta->splits && tb->splits)
00759         {
00760             GList *node_a, *node_b;
00761 
00762             for (node_a = ta->splits, node_b = tb->splits;
00763                     node_a;
00764                     node_a = node_a->next, node_b = node_b->next)
00765             {
00766                 Split *split_a = node_a->data;
00767                 Split *split_b;
00768 
00769                 /* don't presume that the splits are in the same order */
00770                 if (!assume_ordered)
00771                     node_b = g_list_find_custom (tb->splits, split_a,
00772                                                  compare_split_guids);
00773 
00774                 if (!node_b)
00775                 {
00776                     PWARN ("first has split %s and second does not",
00777                            guid_to_string (xaccSplitGetGUID (split_a)));
00778                     return FALSE;
00779                 }
00780 
00781                 split_b = node_b->data;
00782 
00783                 if (!xaccSplitEqual (split_a, split_b, check_guids, check_balances,
00784                                      FALSE))
00785                 {
00786                     char str_a[GUID_ENCODING_LENGTH+1];
00787                     char str_b[GUID_ENCODING_LENGTH+1];
00788 
00789                     guid_to_string_buff (xaccSplitGetGUID (split_a), str_a);
00790                     guid_to_string_buff (xaccSplitGetGUID (split_b), str_b);
00791 
00792                     PWARN ("splits %s and %s differ", str_a, str_b);
00793                     return FALSE;
00794                 }
00795             }
00796 
00797             if (g_list_length (ta->splits) != g_list_length (tb->splits))
00798             {
00799                 PWARN ("different number of splits");
00800                 return FALSE;
00801             }
00802         }
00803     }
00804 
00805     return TRUE;
00806 }

gnc_numeric xaccTransGetAccountAmount ( const Transaction trans,
const Account account 
)

Same as xaccTransGetAccountValue, but uses the Account's commodity.

Definition at line 957 of file Transaction.c.

00958 {
00959     gnc_numeric total = gnc_numeric_zero ();
00960     if (!trans || !acc) return total;
00961 
00962     total = gnc_numeric_convert (total, xaccAccountGetCommoditySCU (acc),
00963                                  GNC_RND_ROUND);
00964     FOR_EACH_SPLIT(trans, if (acc == xaccSplitGetAccount(s))
00965                    total = gnc_numeric_add_fixed(
00966                                total, xaccSplitGetAmount(s)));
00967     return total;
00968 }

gnc_numeric xaccTransGetAccountBalance ( const Transaction trans,
const Account account 
)

Get the account balance for the specified account after the last split in the specified transaction.

Definition at line 1031 of file Transaction.c.

01033 {
01034     GList *node;
01035     Split *last_split = NULL;
01036 
01037     // Not really the appropriate error value.
01038     g_return_val_if_fail(account && trans, gnc_numeric_error(GNC_ERROR_ARG));
01039 
01040     for (node = trans->splits; node; node = node->next)
01041     {
01042         Split *split = node->data;
01043 
01044         if (!xaccTransStillHasSplit(trans, split))
01045             continue;
01046         if (xaccSplitGetAccount(split) != account)
01047             continue;
01048 
01049         if (!last_split)
01050         {
01051             last_split = split;
01052             continue;
01053         }
01054 
01055         /* This test needs to correspond to the comparison function used when
01056            sorting the splits for computing the running balance. */
01057         if (xaccSplitOrder (last_split, split) < 0)
01058             last_split = split;
01059     }
01060 
01061     return xaccSplitGetBalance (last_split);
01062 }

gnc_numeric xaccTransGetAccountValue ( const Transaction trans,
const Account account 
)

The xaccTransGetAccountValue() method returns the total value applied to a particular account. In some cases there may be multiple Splits in a single Transaction applied to one account (in particular when trying to balance Lots) -- this function is just a convienience to view everything at once.

Definition at line 941 of file Transaction.c.

00943 {
00944     gnc_numeric total = gnc_numeric_zero ();
00945     if (!trans || !acc) return total;
00946 
00947     FOR_EACH_SPLIT(trans, if (acc == xaccSplitGetAccount(s))
00948 {
00949     total = gnc_numeric_add (total, xaccSplitGetValue (s),
00950                              GNC_DENOM_AUTO,
00951                              GNC_HOW_DENOM_EXACT);
00952     });
00953     return total;
00954 }

gnc_commodity* xaccTransGetCurrency ( const Transaction trans  ) 

Returns the valuation commodity of this transaction.

Each transaction's valuation commodity, or 'currency' is, by definition, the common currency in which all splits in the transaction can be valued. The total value of the transaction must be zero when all splits are valued in this currency.

Note:
What happens if the Currency isn't set? Ans: bad things.

Definition at line 1069 of file Transaction.c.

01070 {
01071     return trans ? trans->common_currency : NULL;
01072 }

time_t xaccTransGetDate ( const Transaction trans  ) 

Retrieve the posted date of the transaction. The posted date is the date when this transaction was posted at the bank. (Although having different function names, GetDate and GetDatePosted refer to the same single date.)

Definition at line 1810 of file Transaction.c.

01811 {
01812     return trans ? trans->date_posted.tv_sec : 0;
01813 }

void xaccTransGetDateDueTS ( const Transaction trans,
Timespec ts 
)

Dates and txn-type for A/R and A/P "invoice" postings

Definition at line 1844 of file Transaction.c.

01845 {
01846     KvpValue *value;
01847 
01848     if (!trans || !ts) return;
01849 
01850     value = kvp_frame_get_slot (trans->inst.kvp_data, TRANS_DATE_DUE_KVP);
01851     if (value)
01852         *ts = kvp_value_get_timespec (value);
01853     else
01854         xaccTransGetDatePostedTS (trans, ts);
01855 }

void xaccTransGetDateEnteredTS ( const Transaction trans,
Timespec ts 
)

Retrieve the date of when the transaction was entered. The entered date is the date when the register entry was made.

Definition at line 1823 of file Transaction.c.

01824 {
01825     if (trans && ts)
01826         *ts = trans->date_entered;
01827 }

void xaccTransGetDatePostedTS ( const Transaction trans,
Timespec ts 
)

Retrieve the posted date of the transaction. The posted date is the date when this transaction was posted at the bank. (Although having different function names, GetDate and GetDatePosted refer to the same single date.)

Definition at line 1816 of file Transaction.c.

01817 {
01818     if (trans && ts)
01819         *ts = trans->date_posted;
01820 }

const char* xaccTransGetDescription ( const Transaction trans  ) 

Gets the transaction Description

Definition at line 1794 of file Transaction.c.

01795 {
01796     return trans ? trans->description : NULL;
01797 }

MonetaryList* xaccTransGetImbalance ( const Transaction trans  ) 

The xaccTransGetImbalance method returns a list giving the value of the transaction in each currency for which the balance is not zero. If the use of currency accounts is disabled, then this will be only the common currency for the transaction and xaccTransGetImbalance becomes equivalent to xaccTransGetImbalanceValue. Otherwise it will return a list containing the imbalance in each currency.

Definition at line 852 of file Transaction.c.

00853 {
00854     /* imbal_value is used if either (1) the transaction has a non currency
00855        split or (2) all the splits are in the same currency.  If there are
00856        no non-currency splits and not all splits are in the same currency then
00857        imbal_list is used to compute the imbalance. */
00858     MonetaryList *imbal_list = NULL;
00859     gnc_numeric imbal_value = gnc_numeric_zero();
00860     gboolean trading_accts;
00861 
00862     if (!trans) return imbal_list;
00863 
00864     ENTER("(trans=%p)", trans);
00865 
00866     trading_accts = xaccTransUseTradingAccounts (trans);
00867 
00868     /* If using trading accounts and there is at least one split that is not
00869        in the transaction currency or a split that has a price or exchange
00870        rate other than 1, then compute the balance in each commodity in the
00871        transaction.  Otherwise (all splits are in the transaction's currency)
00872        then compute the balance using the value fields.
00873 
00874        Optimize for the common case of only one currency and a balanced
00875        transaction. */
00876     FOR_EACH_SPLIT(trans,
00877     {
00878         gnc_commodity *commodity;
00879         commodity = xaccAccountGetCommodity(xaccSplitGetAccount(s));
00880         if (trading_accts &&
00881         (imbal_list ||
00882         ! gnc_commodity_equiv(commodity, trans->common_currency) ||
00883         ! gnc_numeric_equal(xaccSplitGetAmount(s), xaccSplitGetValue(s))))
00884         {
00885             /* Need to use (or already are using) a list of imbalances in each of
00886                the currencies used in the transaction. */
00887             if (! imbal_list)
00888             {
00889                 /* All previous splits have been in the transaction's common
00890                    currency, so imbal_value is in this currency. */
00891                 imbal_list = gnc_monetary_list_add_value(imbal_list,
00892                 trans->common_currency,
00893                 imbal_value);
00894             }
00895             imbal_list = gnc_monetary_list_add_value(imbal_list, commodity,
00896             xaccSplitGetAmount(s));
00897         }
00898 
00899         /* Add it to the value accumulator in case we need it. */
00900         imbal_value = gnc_numeric_add(imbal_value, xaccSplitGetValue(s),
00901         GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
00902     } );
00903 
00904 
00905     if (!imbal_list && !gnc_numeric_zero_p(imbal_value))
00906     {
00907         /* Not balanced and no list, create one.  If we found multiple currencies
00908            and no non-currency commodity then imbal_list will already exist and
00909            we won't get here. */
00910         imbal_list = gnc_monetary_list_add_value(imbal_list,
00911                      trans->common_currency,
00912                      imbal_value);
00913     }
00914 
00915     /* Delete all the zero entries from the list, perhaps leaving an
00916        empty list */
00917     imbal_list = gnc_monetary_list_delete_zeros(imbal_list);
00918 
00919     LEAVE("(trans=%p), imbal=%p", trans, imbal_list);
00920     return imbal_list;
00921 }

gnc_numeric xaccTransGetImbalanceValue ( const Transaction trans  ) 

The xaccTransGetImbalanceValue() method returns the total value of the transaction. In a pure double-entry system, this imbalance should be exactly zero, and if it is not, something is broken. However, when double-entry semantics are not enforced, unbalanced transactions can sneak in, and this routine can be used to find out how much things are off by. The value returned is denominated in the currency that is returned by the xaccTransFindCommonCurrency() method.

If the use of currency exchange accounts is enabled then the a a transaction must be balanced in each currency it uses to be considered to be balanced. The method xaccTransGetImbalance is used by most code to take this into consideration. This method is only used in a few places that want the transaction value even if currency exchange accounts are enabled.

Definition at line 836 of file Transaction.c.

00837 {
00838     gnc_numeric imbal = gnc_numeric_zero();
00839     if (!trans) return imbal;
00840 
00841     ENTER("(trans=%p)", trans);
00842     /* Could use xaccSplitsComputeValue, except that we want to use
00843        GNC_HOW_DENOM_EXACT */
00844     FOR_EACH_SPLIT(trans, imbal =
00845                        gnc_numeric_add(imbal, xaccSplitGetValue(s),
00846                                        GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT));
00847     LEAVE("(trans=%p) imbal=%s", trans, gnc_num_dbg_to_string(imbal));
00848     return imbal;
00849 }

const char* xaccTransGetNotes ( const Transaction trans  ) 

Gets the transaction Notes

The Notes field is only visible in the register in double-line mode

Definition at line 1800 of file Transaction.c.

01801 {
01802     return trans ?
01803            kvp_frame_get_string (trans->inst.kvp_data, trans_notes_str) : NULL;
01804 }

const char* xaccTransGetNum ( const Transaction trans  ) 

Gets the transaction Number (or ID) field

Definition at line 1788 of file Transaction.c.

01789 {
01790     return trans ? trans->num : NULL;
01791 }

const char* xaccTransGetReadOnly ( const Transaction trans  ) 

FIXME: document me

Definition at line 1877 of file Transaction.c.

01878 {
01879     /* XXX This flag should be cached in the transaction structure
01880      * for performance reasons, since its checked every trans commit.
01881      */
01882     return trans ? kvp_frame_get_string (
01883                trans->inst.kvp_data, TRANS_READ_ONLY_REASON) : NULL;
01884 }

Transaction* xaccTransGetReversedBy ( const Transaction trans  ) 

Returns the transaction that reversed the given transaction.

Parameters:
trans a Transaction that has been reversed
Returns:
the transaction that reversed the given transaction, or NULL if the given transaction has not been reversed.

Definition at line 2089 of file Transaction.c.

02090 {
02091     GUID *guid;
02092 
02093     g_return_val_if_fail(trans, NULL);
02094     guid = kvp_frame_get_guid(trans->inst.kvp_data, TRANS_REVERSED_BY);
02095     return xaccTransLookup(guid, qof_instance_get_book(trans));
02096 }

Split* xaccTransGetSplit ( const Transaction trans,
int  i 
)

The xaccTransGetSplit() method returns a pointer to each of the splits in this transaction.

Parameters:
trans The transaction
i The split number. Valid values for i are zero to (number_of__splits-1). An invalid value of i will cause NULL to be returned. A convenient way of cycling through all splits is to start at zero, and keep incrementing until a null value is returned.

Definition at line 1754 of file Transaction.c.

01755 {
01756     int j = 0;
01757     if (!trans || i < 0) return NULL;
01758 
01759     FOR_EACH_SPLIT(trans, { if (i == j) return s; j++; });
01760     return NULL;
01761 }

int xaccTransGetSplitIndex ( const Transaction trans,
const Split split 
)

Inverse of xaccTransGetSplit()

Definition at line 1764 of file Transaction.c.

01765 {
01766     int j = 0;
01767     g_return_val_if_fail(trans && split, -1);
01768 
01769     FOR_EACH_SPLIT(trans, { if (s == split) return j; j++; });
01770     return -1;
01771 }

SplitList* xaccTransGetSplitList ( const Transaction trans  ) 

The xaccTransGetSplitList() method returns a GList of the splits in a transaction.

Returns:
The list of splits. This list must NOT be modified. Do *NOT* free this list when you are done with it.

Definition at line 1774 of file Transaction.c.

01775 {
01776     return trans ? trans->splits : NULL;
01777 }

char xaccTransGetTxnType ( const Transaction trans  ) 

Returns the Transaction Type

See TXN_TYPE_NONE, TXN_TYPE_INVOICE and TXN_TYPE_PAYMENT

Definition at line 1866 of file Transaction.c.

01867 {
01868     const char *s;
01869     if (!trans) return TXN_TYPE_NONE;
01870     s = kvp_frame_get_string (trans->inst.kvp_data, TRANS_TXN_TYPE_KVP);
01871     if (s) return *s;
01872 
01873     return TXN_TYPE_NONE;
01874 }

const char* xaccTransGetVoidReason ( const Transaction transaction  ) 

Returns the user supplied textual reason why a transaction was voided.

Parameters:
transaction The transaction in question.
Returns:
A pointer to the user supplied reason for voiding.

Definition at line 2016 of file Transaction.c.

02017 {
02018     g_return_val_if_fail(trans, NULL);
02019     return kvp_frame_get_string(trans->inst.kvp_data, void_reason_str);
02020 }

gboolean xaccTransGetVoidStatus ( const Transaction transaction  ) 

Retrieve information on whether or not a transaction has been voided.

Parameters:
transaction The transaction in question.
Returns:
TRUE if the transaction is void, FALSE otherwise. Also returns FALSE upon an error.

Definition at line 2009 of file Transaction.c.

02010 {
02011     g_return_val_if_fail(trans, FALSE);
02012     return (kvp_frame_get_slot(trans->inst.kvp_data, void_reason_str) != NULL);
02013 }

Timespec xaccTransGetVoidTime ( const Transaction tr  ) 

Returns the time that a transaction was voided.

Parameters:
tr The transaction in question.
Returns:
A Timespec containing the time that this transaction was voided. Returns a time of zero upon error.

Definition at line 2023 of file Transaction.c.

02024 {
02025     const char *val;
02026     Timespec void_time = {0, 0};
02027 
02028     g_return_val_if_fail(tr, void_time);
02029 
02030     val = kvp_frame_get_string(tr->inst.kvp_data, void_time_str);
02031     return val ? gnc_iso8601_to_timespec_gmt(val) : void_time;
02032 }

gboolean xaccTransHasReconciledSplits ( const Transaction trans  ) 

FIXME: document me

Definition at line 1916 of file Transaction.c.

01917 {
01918     return xaccTransHasReconciledSplitsByAccount (trans, NULL);
01919 }

gboolean xaccTransHasReconciledSplitsByAccount ( const Transaction trans,
const Account account 
)

FIXME: document me

Definition at line 1887 of file Transaction.c.

01889 {
01890     GList *node;
01891 
01892     for (node = xaccTransGetSplitList (trans); node; node = node->next)
01893     {
01894         Split *split = node->data;
01895 
01896         if (!xaccTransStillHasSplit(trans, split))
01897             continue;
01898         if (account && (xaccSplitGetAccount(split) != account))
01899             continue;
01900 
01901         switch (xaccSplitGetReconcile (split))
01902         {
01903         case YREC:
01904         case FREC:
01905             return TRUE;
01906 
01907         default:
01908             break;
01909         }
01910     }
01911 
01912     return FALSE;
01913 }

gboolean xaccTransHasSplitsInState ( const Transaction trans,
const char  state 
)

FIXME: document me

Definition at line 1946 of file Transaction.c.

01947 {
01948     return xaccTransHasSplitsInStateByAccount (trans, state, NULL);
01949 }

gboolean xaccTransHasSplitsInStateByAccount ( const Transaction trans,
const char  state,
const Account account 
)

FIXME: document me

Definition at line 1923 of file Transaction.c.

01926 {
01927     GList *node;
01928 
01929     for (node = xaccTransGetSplitList (trans); node; node = node->next)
01930     {
01931         Split *split = node->data;
01932 
01933         if (!xaccTransStillHasSplit(trans, split))
01934             continue;
01935         if (account && (xaccSplitGetAccount(split) != account))
01936             continue;
01937 
01938         if (split->reconciled == state)
01939             return TRUE;
01940     }
01941 
01942     return FALSE;
01943 }

gboolean xaccTransIsBalanced ( const Transaction trans  ) 

Returns true if the transaction is balanced according to the rules currently in effect.

Definition at line 924 of file Transaction.c.

00925 {
00926     MonetaryList *imbal_list;
00927     gboolean result;
00928     if (! gnc_numeric_zero_p(xaccTransGetImbalanceValue(trans)))
00929         return FALSE;
00930 
00931     if (!xaccTransUseTradingAccounts (trans))
00932         return TRUE;
00933 
00934     imbal_list = xaccTransGetImbalance(trans);
00935     result = imbal_list == NULL;
00936     gnc_monetary_list_free(imbal_list);
00937     return result;
00938 }

gboolean xaccTransIsOpen ( const Transaction trans  ) 

The xaccTransIsOpen() method returns TRUE if the transaction is open for editing. Otherwise, it returns false. XXX this routne should probably be deprecated. its, umm, hard to imagine legitimate uses (but it is used by the import/export code for reasons I can't understand.)

Definition at line 1503 of file Transaction.c.

01504 {
01505     return trans ? (0 < qof_instance_get_editlevel(trans)) : FALSE;
01506 }

Transaction* xaccTransLookup ( const GUID *  guid,
QofBook book 
)

The xaccTransLookup() subroutine will return the transaction associated with the given id, or NULL if there is no such transaction.

Definition at line 824 of file Transaction.c.

00825 {
00826     QofCollection *col;
00827     if (!guid || !book) return NULL;
00828     col = qof_book_get_collection (book, GNC_ID_TRANS);
00829     return (Transaction *) qof_collection_lookup_entity (col, guid);
00830 }

int xaccTransOrder ( const Transaction ta,
const Transaction tb 
)

The xaccTransOrder(ta,tb) method is useful for sorting. Orders ta and tb return <0 if ta sorts before tb return >0 if ta sorts after tb return 0 if they are absolutely equal

The comparrison uses the following fields, in order: date posted (compare as a date) num field (compare as an integer) date entered (compare as a date) description field (comcpare as a string using strcmp()) GUID (compare as a guid) Finally, it returns zero if all of the above match. Note that it does *NOT* compare its member splits.

Definition at line 1511 of file Transaction.c.

01512 {
01513     char *da, *db;
01514     int na, nb, retval;
01515 
01516     if ( ta && !tb ) return -1;
01517     if ( !ta && tb ) return +1;
01518     if ( !ta && !tb ) return 0;
01519 
01520     /* if dates differ, return */
01521     DATE_CMP(ta, tb, date_posted);
01522 
01523     /* otherwise, sort on number string */
01524     na = atoi(ta->num);
01525     nb = atoi(tb->num);
01526     if (na < nb) return -1;
01527     if (na > nb) return +1;
01528 
01529     /* if dates differ, return */
01530     DATE_CMP(ta, tb, date_entered);
01531 
01532     /* otherwise, sort on description string */
01533     da = ta->description ? ta->description : "";
01534     db = tb->description ? tb->description : "";
01535     retval = g_utf8_collate (da, db);
01536     if (retval)
01537         return retval;
01538 
01539     /* else, sort on guid - keeps sort stable. */
01540     return qof_instance_guid_compare(ta, tb);
01541 }

Timespec xaccTransRetDateDueTS ( const Transaction trans  ) 

Dates and txn-type for A/R and A/P "invoice" postings

Definition at line 1858 of file Transaction.c.

01859 {
01860     Timespec ts = {0, 0};
01861     if (trans) xaccTransGetDateDueTS (trans, &ts);
01862     return ts;
01863 }

Timespec xaccTransRetDateEnteredTS ( const Transaction trans  ) 

Retrieve the date of when the transaction was entered. The entered date is the date when the register entry was made.

Definition at line 1837 of file Transaction.c.

01838 {
01839     Timespec ts = {0, 0};
01840     return trans ? trans->date_entered : ts;
01841 }

Timespec xaccTransRetDatePostedTS ( const Transaction trans  ) 

Retrieve the posted date of the transaction. The posted date is the date when this transaction was posted at the bank. (Although having different function names, GetDate and GetDatePosted refer to the same single date.)

Definition at line 1830 of file Transaction.c.

01831 {
01832     Timespec ts = {0, 0};
01833     return trans ? trans->date_posted : ts;
01834 }

Transaction* xaccTransReverse ( Transaction transaction  ) 

xaccTransReverse creates a Transaction that reverses the given tranaction by inverting all the numerical values in the given transaction. This function cancels out the effect of an earlier transaction. This will be needed by write only accounts as a way to void a previous transaction (since you can't alter the existing transaction).

Parameters:
transaction The transaction to create a reverse of.
Returns:
a new transaction which reverses the given transaction

Definition at line 2062 of file Transaction.c.

02063 {
02064     Transaction *trans;
02065     kvp_value *kvp_val;
02066     g_return_val_if_fail(orig, NULL);
02067 
02068     trans = xaccTransClone(orig);
02069     xaccTransBeginEdit(trans);
02070 
02071     /* Reverse the values on each split. Clear per-split info. */
02072     FOR_EACH_SPLIT(trans,
02073     {
02074         xaccSplitSetAmount(s, gnc_numeric_neg(xaccSplitGetAmount(s)));
02075         xaccSplitSetValue(s, gnc_numeric_neg(xaccSplitGetValue(s)));
02076         xaccSplitSetReconcile(s, NREC);
02077         qof_instance_set_dirty(QOF_INSTANCE(trans));
02078     });
02079 
02080     /* Now update the original with a pointer to the new one */
02081     kvp_val = kvp_value_new_guid(xaccTransGetGUID(trans));
02082     kvp_frame_set_slot_nc(orig->inst.kvp_data, TRANS_REVERSED_BY, kvp_val);
02083 
02084     xaccTransCommitEdit(trans);
02085     return trans;
02086 }

void xaccTransRollbackEdit ( Transaction trans  ) 

The xaccTransRollbackEdit() routine rejects all edits made, and sets the transaction back to where it was before the editing started. This includes restoring any deleted splits, removing any added splits, and undoing the effects of xaccTransDestroy, as well as restoring share quantities, memos, descriptions, etc.

Todo:
Fix transrollbackedit in QOF so that rollback is exposed via the API.

Definition at line 1364 of file Transaction.c.

01365 {
01366     GList *node, *onode;
01367     QofBackend *be;
01368     Transaction *orig;
01369     GList *slist;
01370     int num_preexist, i;
01371     ENTER ("trans addr=%p\n", trans);
01372 
01373     check_open(trans);
01374 
01375     /* copy the original values back in. */
01376     orig = trans->orig;
01377     SWAP(trans->num, orig->num);
01378     SWAP(trans->description, orig->description);
01379     trans->date_entered = orig->date_entered;
01380     trans->date_posted = orig->date_posted;
01381     SWAP(trans->common_currency, orig->common_currency);
01382     SWAP(trans->inst.kvp_data, orig->inst.kvp_data);
01383 
01384     /* The splits at the front of trans->splits are exactly the same
01385        splits as in the original, but some of them may have changed, so
01386        we restore only those. */
01387     num_preexist = g_list_length(orig->splits);
01388     slist = g_list_copy(trans->splits);
01389     for (i = 0, node = slist, onode = orig->splits; node;
01390             i++, node = node->next, onode = onode ? onode->next : NULL)
01391     {
01392         Split *s = node->data;
01393 
01394         if (!qof_instance_is_dirty(QOF_INSTANCE(s)))
01395             continue;
01396 
01397         if (i < num_preexist)
01398         {
01399             Split *so = onode->data;
01400 
01401             xaccSplitRollbackEdit(s);
01402             SWAP(s->action, so->action);
01403             SWAP(s->memo, so->memo);
01404             SWAP(s->inst.kvp_data, so->inst.kvp_data);
01405             s->reconciled = so->reconciled;
01406             s->amount = so->amount;
01407             s->value = so->value;
01408             s->lot = so->lot;
01409             s->gains_split = s->gains_split;
01410             //SET_GAINS_A_VDIRTY(s);
01411             s->date_reconciled = so->date_reconciled;
01412             qof_instance_mark_clean(QOF_INSTANCE(s));
01413             xaccFreeSplit(so);
01414         }
01415         else
01416         {
01417             /* Potentially added splits */
01418             if (trans != xaccSplitGetParent(s))
01419             {
01420                 trans->splits = g_list_remove(trans->splits, s);
01421                 /* New split added, but then moved to another
01422                    transaction */
01423                 continue;
01424             }
01425             xaccSplitRollbackEdit(s);
01426             trans->splits = g_list_remove(trans->splits, s);
01427             g_assert(trans != xaccSplitGetParent(s));
01428             /* NB: our memory management policy here is that a new split
01429                added to the transaction which is then rolled-back still
01430                belongs to the engine.  Specifically, it's freed by the
01431                transaction to which it was added.  Don't add the Split to
01432                more than one transaction during the begin/commit block! */
01433             if (NULL == xaccSplitGetParent(s))
01434             {
01435                 xaccFreeSplit(s);  // a newly malloc'd split
01436             }
01437         }
01438     }
01439     g_list_free(slist);
01440     g_list_free(orig->splits);
01441     orig->splits = NULL;
01442 
01443     /* Now that the engine copy is back to its original version,
01444      * get the backend to fix it in the database */
01445     be = qof_book_get_backend(qof_instance_get_book(trans));
01448     if (be && be->rollback)
01449     {
01450         QofBackendError errcode;
01451 
01452         /* clear errors */
01453         do
01454         {
01455             errcode = qof_backend_get_error (be);
01456         }
01457         while (ERR_BACKEND_NO_ERR != errcode);
01458 
01459         (be->rollback) (be, &(trans->inst));
01460 
01461         errcode = qof_backend_get_error (be);
01462         if (ERR_BACKEND_MOD_DESTROY == errcode)
01463         {
01464             /* The backend is asking us to delete this transaction.
01465              * This typically happens because another (remote) user
01466              * has deleted this transaction, and we haven't found
01467              * out about it until this user tried to edit it.
01468              */
01469             xaccTransDestroy (trans);
01470             do_destroy (trans);
01471 
01472             /* push error back onto the stack */
01473             qof_backend_set_error (be, errcode);
01474             LEAVE ("deleted trans addr=%p\n", trans);
01475             return;
01476         }
01477         if (ERR_BACKEND_NO_ERR != errcode)
01478         {
01479             PERR ("Rollback Failed.  Ouch!");
01480             /* push error back onto the stack */
01481             qof_backend_set_error (be, errcode);
01482         }
01483     }
01484 
01485     xaccTransWriteLog (trans, 'R');
01486 
01487     xaccFreeTransaction (trans->orig);
01488 
01489     trans->orig = NULL;
01490     qof_instance_set_destroying(trans, FALSE);
01491 
01492     /* Put back to zero. */
01493     qof_instance_decrease_editlevel(trans);
01494     /* FIXME: The register code seems to depend on the engine to
01495        generate an event during rollback, even though the state is just
01496        reverting to what it was. */
01497     gen_event_trans (trans);
01498 
01499     LEAVE ("trans addr=%p\n", trans);
01500 }

void xaccTransScrubGains ( Transaction trans,
Account gain_acc 
)

The xaccTransScrubGains() routine performs a number of cleanup functions on the indicated transaction, with the end-goal of setting up a consistent set of gains/losses for all the splits in the transaction. This includes making sure that the lot assignments of all the splits are good, and that the lots balance appropriately.

Definition at line 2161 of file Transaction.c.

02162 {
02163     SplitList *node;
02164 
02165     ENTER("(trans=%p)", trans);
02166     /* Lock down posted date, its to be synced to the posted date
02167      * for the source of the cap gains. */
02168     xaccTransScrubGainsDate(trans);
02169 
02170     /* Fix up the split amount */
02171 restart:
02172     for (node = trans->splits; node; node = node->next)
02173     {
02174         Split *s = node->data;
02175 
02176         if (!xaccTransStillHasSplit(trans, s)) continue;
02177 
02178         xaccSplitDetermineGainStatus(s);
02179         if (s->gains & GAINS_STATUS_ADIRTY)
02180         {
02181             gboolean altered = FALSE;
02182             s->gains &= ~GAINS_STATUS_ADIRTY;
02183             if (s->lot)
02184                 altered = xaccScrubLot(s->lot);
02185             else
02186                 altered = xaccSplitAssign(s);
02187             if (altered) goto restart;
02188         }
02189     }
02190 
02191     /* Fix up gains split value */
02192     FOR_EACH_SPLIT(trans,
02193                    if ((s->gains & GAINS_STATUS_VDIRTY) ||
02194                        (s->gains_split &&
02195                         (s->gains_split->gains & GAINS_STATUS_VDIRTY)))
02196                    xaccSplitComputeCapGains(s, gain_acc);
02197                   );
02198 
02199     LEAVE("(trans=%p)", trans);
02200 }

void xaccTransSetCurrency ( Transaction trans,
gnc_commodity curr 
)

Set the commodity of this transaction.

Definition at line 1075 of file Transaction.c.

01076 {
01077     gint fraction, old_fraction;
01078 
01079     if (!trans || !curr || trans->common_currency == curr) return;
01080     xaccTransBeginEdit(trans);
01081 
01082     old_fraction = gnc_commodity_get_fraction (trans->common_currency);
01083     trans->common_currency = curr;
01084     fraction = gnc_commodity_get_fraction (curr);
01085 
01086     /* avoid needless crud if fraction didn't change */
01087     if (fraction != old_fraction)
01088     {
01089         FOR_EACH_SPLIT(trans, xaccSplitSetValue(s, xaccSplitGetValue(s)));
01090     }
01091 
01092     qof_instance_set_dirty(QOF_INSTANCE(trans));
01093     mark_trans(trans);  /* Dirty balance of every account in trans */
01094     xaccTransCommitEdit(trans);
01095 }

void xaccTransSetDate ( Transaction trans,
int  day,
int  mon,
int  year 
)

The xaccTransSetDate() method does the same thing as xaccTransSetDate[Posted]Secs(), but takes a convenient day-month-year format.

(Footnote: this shouldn't matter to a user, but anyone modifying the engine should understand that when xaccTransCommitEdit() is called, the date order of each of the component splits will be checked, and will be restored in ascending date order.)

Definition at line 1632 of file Transaction.c.

01633 {
01634     Timespec ts;
01635     if (!trans) return;
01636     ts = gnc_dmy2timespec(day, mon, year);
01637     xaccTransSetDateInternal(trans, &trans->date_posted, ts);
01638     set_gains_date_dirty (trans);
01639 }

void xaccTransSetDateDueTS ( Transaction trans,
const Timespec ts 
)

Dates and txn-type for A/R and A/P "invoice" postings

Definition at line 1642 of file Transaction.c.

01643 {
01644     if (!trans || !ts) return;
01645     xaccTransBeginEdit(trans);
01646     kvp_frame_set_timespec (trans->inst.kvp_data, TRANS_DATE_DUE_KVP, *ts);
01647     qof_instance_set_dirty(QOF_INSTANCE(trans));
01648     xaccTransCommitEdit(trans);
01649 }

void xaccTransSetDateEnteredSecs ( Transaction trans,
time_t  time 
)

Modify the date of when the transaction was entered. The entered date is the date when the register entry was made.

Definition at line 1588 of file Transaction.c.

01589 {
01590     Timespec ts = {secs, 0};
01591     if (!trans) return;
01592     xaccTransSetDateInternal(trans, &trans->date_entered, ts);
01593 }

void xaccTransSetDateEnteredTS ( Transaction trans,
const Timespec ts 
)

Modify the date of when the transaction was entered. The entered date is the date when the register entry was made.

Definition at line 1625 of file Transaction.c.

01626 {
01627     if (!trans || !ts) return;
01628     xaccTransSetDateInternal(trans, &trans->date_entered, *ts);
01629 }

void xaccTransSetDatePostedTS ( Transaction trans,
const Timespec ts 
)

The xaccTransSetDatePostedTS() method does the same thing as xaccTransSetDatePostedSecs(), but takes a struct timespec64.

Definition at line 1607 of file Transaction.c.

01608 {
01609     if (!trans || !ts) return;
01610     xaccTransSetDateInternal(trans, &trans->date_posted, *ts);
01611     set_gains_date_dirty (trans);
01612 }

void xaccTransSetDescription ( Transaction trans,
const char *  desc 
)

Sets the transaction Description

Definition at line 1721 of file Transaction.c.

01722 {
01723     if (!trans || !desc) return;
01724     xaccTransBeginEdit(trans);
01725 
01726     CACHE_REPLACE(trans->description, desc);
01727     qof_instance_set_dirty(QOF_INSTANCE(trans));
01728     xaccTransCommitEdit(trans);
01729 }

void xaccTransSetNotes ( Transaction trans,
const char *  notes 
)

Sets the transaction Notes

The Notes field is only visible in the register in double-line mode

Definition at line 1740 of file Transaction.c.

01741 {
01742     if (!trans || !notes) return;
01743     xaccTransBeginEdit(trans);
01744 
01745     kvp_frame_set_str (trans->inst.kvp_data, trans_notes_str, notes);
01746     qof_instance_set_dirty(QOF_INSTANCE(trans));
01747     xaccTransCommitEdit(trans);
01748 }

void xaccTransSetNum ( Transaction trans,
const char *  num 
)

Sets the transaction Number (or ID) field

Definition at line 1701 of file Transaction.c.

01702 {
01703     if (!trans || !xnum) return;
01704     xaccTransBeginEdit(trans);
01705 
01706     CACHE_REPLACE(trans->num, xnum);
01707     qof_instance_set_dirty(QOF_INSTANCE(trans));
01708     mark_trans(trans);  /* Dirty balance of every account in trans */
01709     xaccTransCommitEdit(trans);
01710 }

void xaccTransSetReadOnly ( Transaction trans,
const char *  reason 
)

Set the transaction to be ReadOnly

Definition at line 1675 of file Transaction.c.

01676 {
01677     if (trans && reason)
01678     {
01679         xaccTransBeginEdit(trans);
01680         kvp_frame_set_str (trans->inst.kvp_data,
01681                            TRANS_READ_ONLY_REASON, reason);
01682         qof_instance_set_dirty(QOF_INSTANCE(trans));
01683         xaccTransCommitEdit(trans);
01684     }
01685 }

void xaccTransSetTxnType ( Transaction trans,
char  type 
)

Set the Transaction Type

See TXN_TYPE_NONE, TXN_TYPE_INVOICE and TXN_TYPE_PAYMENT

Definition at line 1652 of file Transaction.c.

01653 {
01654     char s[2] = {type, '\0'};
01655     g_return_if_fail(trans);
01656     xaccTransBeginEdit(trans);
01657     kvp_frame_set_str (trans->inst.kvp_data, TRANS_TXN_TYPE_KVP, s);
01658     qof_instance_set_dirty(QOF_INSTANCE(trans));
01659     xaccTransCommitEdit(trans);
01660 }

void xaccTransSortSplits ( Transaction trans  ) 

Sorts the splits in a transaction, putting the debits first, followed by the credits.

Definition at line 485 of file Transaction.c.

00486 {
00487     GList *node, *new_list = NULL;
00488     Split *split;
00489 
00490     /* first debits */
00491     for (node = trans->splits; node; node = node->next)
00492     {
00493         split = node->data;
00494         if (gnc_numeric_negative_p (xaccSplitGetValue(split)))
00495             continue;
00496         new_list = g_list_append(new_list, split);
00497     }
00498 
00499     /* then credits */
00500     for (node = trans->splits; node; node = node->next)
00501     {
00502         split = node->data;
00503         if (!gnc_numeric_negative_p (xaccSplitGetValue(split)))
00504             continue;
00505         new_list = g_list_append(new_list, split);
00506     }
00507 
00508     /* install newly sorted list */
00509     g_list_free(trans->splits);
00510     trans->splits = new_list;
00511 }

void xaccTransUnvoid ( Transaction transaction  ) 

xaccTransUnvoid restores a voided transaction to its original state. At some point when gnucash is enhanced to support an audit trail (i.e. write only transactions) this command should be automatically disabled when the audit trail feature is enabled.

Parameters:
transaction The transaction to restore from voided state.

Definition at line 2035 of file Transaction.c.

02036 {
02037     KvpFrame *frame;
02038     KvpValue *val;
02039 
02040     g_return_if_fail(trans);
02041 
02042     frame = trans->inst.kvp_data;
02043     val = kvp_frame_get_slot(frame, void_reason_str);
02044     if (!val) return; /* Transaction isn't voided. Bail. */
02045 
02046     xaccTransBeginEdit(trans);
02047 
02048     val = kvp_frame_get_slot(frame, void_former_notes_str);
02049     kvp_frame_set_slot(frame, trans_notes_str, val);
02050     kvp_frame_set_slot_nc(frame, void_former_notes_str, NULL);
02051     kvp_frame_set_slot_nc(frame, void_reason_str, NULL);
02052     kvp_frame_set_slot_nc(frame, void_time_str, NULL);
02053 
02054     FOR_EACH_SPLIT(trans, xaccSplitUnvoid(s));
02055 
02056     /* Dirtying taken care of by ClearReadOnly */
02057     xaccTransClearReadOnly(trans);
02058     xaccTransCommitEdit(trans);
02059 }

gboolean xaccTransUseTradingAccounts ( const Transaction trans  ) 

Determine whether this transaction should use commodity trading accounts

Definition at line 815 of file Transaction.c.

00816 {
00817     return qof_book_use_trading_accounts(qof_instance_get_book (trans));
00818 }

void xaccTransVoid ( Transaction transaction,
const char *  reason 
)

xaccTransVoid voids a transaction. A void transaction has no values, is unaffected by reconciliation, and, by default is not included in any queries. A voided transaction may not be altered.

Parameters:
transaction The transaction to void.
reason The textual reason why this transaction is being voided.

Definition at line 1978 of file Transaction.c.

01979 {
01980     KvpFrame *frame;
01981     KvpValue *val;
01982     Timespec now;
01983     char iso8601_str[ISO_DATELENGTH+1] = "";
01984 
01985     g_return_if_fail(trans && reason);
01986 
01987     xaccTransBeginEdit(trans);
01988     frame = trans->inst.kvp_data;
01989 
01990     val = kvp_frame_get_slot(frame, trans_notes_str);
01991     kvp_frame_set_slot(frame, void_former_notes_str, val);
01992 
01993     kvp_frame_set_string(frame, trans_notes_str, _("Voided transaction"));
01994     kvp_frame_set_string(frame, void_reason_str, reason);
01995 
01996     now.tv_sec = time(NULL);
01997     now.tv_nsec = 0;
01998     gnc_timespec_to_iso8601_buff(now, iso8601_str);
01999     kvp_frame_set_string(frame, void_time_str, iso8601_str);
02000 
02001     FOR_EACH_SPLIT(trans, xaccSplitVoid(s));
02002 
02003     /* Dirtying taken care of by SetReadOnly */
02004     xaccTransSetReadOnly(trans, _("Transaction Voided"));
02005     xaccTransCommitEdit(trans);
02006 }


Generated on Mon Mar 15 04:43:27 2010 for GnuCash by  doxygen 1.5.7.1