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) |
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 SPLIT_ACCOUNT_GUID "account-guid" |
| #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 xaccSplitGetGUID | ( | X | ) | qof_entity_get_guid(QOF_INSTANCE(X)) |
| #define xaccSplitReturnGUID | ( | X | ) | (X ? *(qof_entity_get_guid(QOF_INSTANCE(X))) : *(guid_null())) |
| #define xaccTransAppendSplit | ( | t, | |||
| s | ) | 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.
Definition at line 293 of file Transaction.h.
| #define xaccTransGetBook | ( | X | ) | qof_instance_get_book (QOF_INSTANCE(X)) |
| #define xaccTransGetGUID | ( | X | ) | qof_entity_get_guid(QOF_INSTANCE(X)) |
| #define xaccTransGetSlots | ( | X | ) | qof_instance_get_slots (QOF_INSTANCE(X)) |
| #define xaccTransReturnGUID | ( | X | ) | (X ? *(qof_entity_get_guid(QOF_INSTANCE(X))) : *(guid_null())) |
| #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.
| guint gnc_book_count_transactions | ( | QofBook * | book | ) |
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 }
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.
| 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 }
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 }
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 }
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 }
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.)
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.
| 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 }
Returns the account of this split, which was set through xaccAccountInsertSplit().
Definition at line 686 of file Split.c.
| const char* xaccSplitGetAction | ( | const Split * | split | ) |
| gnc_numeric xaccSplitGetAmount | ( | const Split * | split | ) |
| 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.
| 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 }
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 | ) |
| 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 }
| const char* xaccSplitGetMemo | ( | 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 | ) |
| char xaccSplitGetReconcile | ( | const Split * | split | ) |
| gnc_numeric xaccSplitGetReconciledBalance | ( | const Split * | split | ) |
| 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 }
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 | ) |
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 }
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 }
| 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 ...
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.
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 }
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 }
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 | |||
| ) |
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 }
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.
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.
| split | The split in question. |
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.
| split | The split in question. |
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 | ) |
| 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.
| 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.
| 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.
Definition at line 1069 of file Transaction.c.
| 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.
| 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.
| 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.
| const char* xaccTransGetDescription | ( | const Transaction * | trans | ) |
| 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 | ) |
| 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.
| trans | a Transaction that has 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.
| 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.
Definition at line 1774 of file Transaction.c.
| 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.
| transaction | The transaction in question. |
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.
| transaction | The transaction in question. |
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.
| tr | The transaction in question. |
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.
| 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).
| transaction | The transaction to create a reverse of. |
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.
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.
| 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.
| 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 }
1.5.7.1