[Gnucash-changes] r13045 - gnucash/trunk/src/engine - Add some
convenience functions for getting values from various combinations
Chris Shoemaker
chris at cvs.gnucash.org
Sun Jan 29 21:59:44 EST 2006
Author: chris
Date: 2006-01-29 21:59:43 -0500 (Sun, 29 Jan 2006)
New Revision: 13045
Trac: http://svn.gnucash.org/trac/changeset/13045
Modified:
gnucash/trunk/src/engine/Transaction.c
gnucash/trunk/src/engine/Transaction.h
gnucash/trunk/src/engine/TransactionP.h
Log:
Add some convenience functions for getting values from various combinations
of Accounts, Transactions, and Splits.
Modified: gnucash/trunk/src/engine/Transaction.c
===================================================================
--- gnucash/trunk/src/engine/Transaction.c 2006-01-30 01:56:13 UTC (rev 13044)
+++ gnucash/trunk/src/engine/Transaction.c 2006-01-30 02:59:43 UTC (rev 13045)
@@ -126,6 +126,36 @@
qof_entity_init (&split->entity, GNC_ID_SPLIT, col);
}
+void
+xaccSplitReinit(Split * split)
+{
+ /* fill in some sane defaults */
+ split->acc = NULL;
+ split->parent = NULL;
+ split->lot = NULL;
+
+ CACHE_REPLACE(split->action, "");
+ CACHE_REPLACE(split->memo, "");
+ split->reconciled = NREC;
+ split->amount = gnc_numeric_zero();
+ split->value = gnc_numeric_zero();
+
+ split->date_reconciled.tv_sec = 0;
+ split->date_reconciled.tv_nsec = 0;
+
+ split->balance = gnc_numeric_zero();
+ split->cleared_balance = gnc_numeric_zero();
+ split->reconciled_balance = gnc_numeric_zero();
+
+ if (split->kvp_data)
+ kvp_frame_delete(split->kvp_data);
+ split->kvp_data = kvp_frame_new();
+ split->idata = 0;
+
+ split->gains = GAINS_STATUS_UNKNOWN;
+ split->gains_split = NULL;
+}
+
/********************************************************************\
\********************************************************************/
@@ -135,7 +165,7 @@
Split *split;
g_return_val_if_fail (book, NULL);
- split = g_new (Split, 1);
+ split = g_new0 (Split, 1);
xaccInitSplit (split, book);
return split;
@@ -188,7 +218,7 @@
return split;
}
-static Split *
+Split *
xaccSplitClone (const Split *s)
{
QofCollection *col;
@@ -432,6 +462,28 @@
return TRUE;
}
+static void
+add_keys_to_list(gpointer key, gpointer val, gpointer list)
+{
+ *(GList **)list = g_list_prepend(*(GList **)list, key);
+}
+
+GList *
+xaccSplitListGetUniqueTransactions(const GList *splits)
+{
+ const GList *node;
+ GList *transList = NULL;
+ GHashTable *transHash = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+ for(node = splits; node; node = node->next) {
+ Transaction *trans = xaccSplitGetParent((Split *)(node->data));
+ g_hash_table_insert(transHash, trans, trans);
+ }
+ g_hash_table_foreach(transHash, add_keys_to_list, &transList);
+ g_hash_table_destroy(transHash);
+ return transList;
+}
+
/********************************************************************
* Account funcs
********************************************************************/
@@ -1409,6 +1461,154 @@
return total;
}
+gnc_numeric
+xaccTransGetAccountAmount (const Transaction *trans, const Account *account)
+{
+ gnc_numeric total = gnc_numeric_zero ();
+ GList *splits;
+
+ if (!trans || !account)
+ return total;
+
+ total = gnc_numeric_convert (total, xaccAccountGetCommoditySCU (account),
+ GNC_RND_ROUND);
+
+ for (splits = xaccTransGetSplitList (trans); splits; splits = splits->next) {
+ Split *s = splits->data;
+ Account *a = xaccSplitGetAccount (s);
+ if (a == account)
+ total = gnc_numeric_add_fixed (total, xaccSplitGetAmount (s));
+ }
+ return total;
+}
+
+gnc_numeric
+xaccTransGetAccountConvRate(Transaction *txn, Account *acc)
+{
+ gnc_numeric amount, value, convrate;
+ GList *splits;
+ Split *s;
+ gboolean found_acc_match = FALSE;
+
+ /* We need to compute the conversion rate into _this account_. So,
+ * find the first split into this account, compute the conversion
+ * rate (based on amount/value), and then return this conversion
+ * rate.
+ */
+ splits = xaccTransGetSplitList(txn);
+ for (; splits; splits = splits->next) {
+ s = splits->data;
+
+ if (xaccSplitGetAccount (s) != acc)
+ continue;
+
+ found_acc_match = TRUE;
+ amount = xaccSplitGetAmount (s);
+
+ /* Ignore splits with "zero" amount */
+ if (gnc_numeric_zero_p (amount))
+ continue;
+
+ value = xaccSplitGetValue (s);
+ if (gnc_numeric_zero_p (value))
+ PWARN("How can amount be nonzero and value be zero?");
+
+ convrate = gnc_numeric_div(amount, value, GNC_DENOM_AUTO, GNC_DENOM_REDUCE);
+ return convrate;
+ }
+
+ if (acc) {
+ /* If we did find a matching account but it's amount was zero,
+ * then perhaps this is a "special" income/loss transaction
+ */
+ if (found_acc_match)
+ return gnc_numeric_zero();
+ else
+ PERR("Cannot convert transaction -- no splits with proper conversion ratio");
+ }
+ return gnc_numeric_create (100, 100);
+}
+
+gnc_numeric
+xaccSplitConvertAmount (Split *split, Account * account)
+{
+ gnc_commodity *acc_com, *to_commodity;
+ Transaction *txn;
+ gnc_numeric amount, value, convrate;
+ Account * split_acc;
+
+ amount = xaccSplitGetAmount (split);
+
+ /* If this split is attached to this account, OR */
+ split_acc = xaccSplitGetAccount (split);
+ if (split_acc == account)
+ return amount;
+
+ /* If split->account->commodity == to_commodity, return the amount */
+ acc_com = xaccAccountGetCommodity (split_acc);
+ to_commodity = xaccAccountGetCommodity (account);
+ if (acc_com && gnc_commodity_equal (acc_com, to_commodity))
+ return amount;
+
+ /* Ok, this split is not for the viewed account, and the commodity
+ * does not match. So we need to do some conversion.
+ *
+ * First, we can cheat. If this transaction is balanced and has
+ * exactly two splits, then we can implicitly determine the exchange
+ * rate and just return the 'other' split amount.
+ */
+ txn = xaccSplitGetParent (split);
+ if (txn && gnc_numeric_zero_p (xaccTransGetImbalance (txn))) {
+ Split *osplit = xaccSplitGetOtherSplit (split);
+
+ if (osplit)
+ return gnc_numeric_neg (xaccSplitGetAmount (osplit));
+ }
+
+ /* ... otherwise, we need to compute the amount from the conversion
+ * rate into _this account_. So, find the split into this account,
+ * compute the conversion rate (based on amount/value), and then multiply
+ * this times the split value.
+ */
+ convrate = xaccTransGetAccountConvRate(txn, account);
+ value = xaccSplitGetValue (split);
+ return gnc_numeric_mul (value, convrate,
+ gnc_commodity_get_fraction (to_commodity),
+ GNC_RND_ROUND);
+}
+
+gnc_numeric
+xaccTransGetAccountBalance (const Transaction *trans,
+ const Account *account)
+{
+ GList *node;
+ Split *last_split = NULL;
+
+ // Not really the appropriate error value.
+ g_return_val_if_fail(account && trans, gnc_numeric_error(GNC_ERROR_ARG));
+
+ for (node = xaccTransGetSplitList(trans); node; node = node->next)
+ {
+ Split *split = node->data;
+
+ if (xaccSplitGetAccount(split) != account)
+ continue;
+
+ if (!last_split)
+ {
+ last_split = split;
+ continue;
+ }
+
+ /* This test needs to correspond to the comparison function used when
+ sorting the splits for computing the running balance. */
+ if (xaccSplitDateOrder (last_split, split) < 0)
+ last_split = split;
+ }
+
+ return xaccSplitGetBalance (last_split);
+}
+
/********************************************************************\
\********************************************************************/
/* The new routine for setting the common currency */
Modified: gnucash/trunk/src/engine/Transaction.h
===================================================================
--- gnucash/trunk/src/engine/Transaction.h 2006-01-30 01:56:13 UTC (rev 13044)
+++ gnucash/trunk/src/engine/Transaction.h 2006-01-30 02:59:43 UTC (rev 13045)
@@ -335,6 +335,30 @@
gnc_numeric xaccTransGetAccountValue (const Transaction *trans,
const Account *account);
+/** Same as xaccTransGetAccountValue, but uses the Account's commodity. */
+gnc_numeric xaccTransGetAccountAmount (const Transaction *trans,
+ const Account *account);
+
+/* Compute the conversion rate for the transaction to this account.
+ * Any "split value" (which is in the transaction currency),
+ * multiplied by this conversion rate, will give you the value you
+ * should display for this account.
+ *
+ * If 'acc' is NULL, return unity.
+ */
+gnc_numeric xaccTransGetAccountConvRate(Transaction *txn, Account *acc);
+
+/* Convert the amount/value of the Split for viewing in the account --
+ * in particular we want to convert the Split to be in to_commodity.
+ * Returns the amount.
+ */
+gnc_numeric xaccSplitConvertAmount (Split *split, Account * account);
+
+/** Get the account balance for the specified account after the last
+ split in the specified transaction. */
+gnc_numeric xaccTransGetAccountBalance (const Transaction *trans,
+ const Account *account);
+
/**
* The xaccTransOrder(ta,tb) method is useful for sorting.
* Orders ta and tb
@@ -436,6 +460,12 @@
/** Constructor. */
Split * xaccMallocSplit (QofBook *book);
+/* Reinit a previously malloc'd split. Split remains in the book it
+ was already in, and the QofEntity portions also remain unchanged.
+ It's basically the data elements that are reverted to default
+ values. */
+void xaccSplitReinit(Split * split);
+
/** Destructor.
*
* The xaccSplitDestroy() method will update its parent account and
@@ -652,6 +682,9 @@
@{
*/
+/* Get a GList of unique transactions containing the given list of Splits. */
+GList *xaccSplitListGetUniqueTransactions(const GList *splits);
+
/** Equality.
*
* @param sa First split to compare
Modified: gnucash/trunk/src/engine/TransactionP.h
===================================================================
--- gnucash/trunk/src/engine/TransactionP.h 2006-01-30 01:56:13 UTC (rev 13044)
+++ gnucash/trunk/src/engine/TransactionP.h 2006-01-30 02:59:43 UTC (rev 13045)
@@ -114,7 +114,6 @@
* "extra" information in splits, transactions, and accounts.
* it's NULL until accessed. */
KvpFrame * kvp_data;
-
Timespec date_reconciled; /* date split was reconciled */
char reconciled; /* The reconciled field */
@@ -221,6 +220,8 @@
*/
void xaccFreeSplit (Split *split); /* frees memory */
+Split * xaccSplitClone (const Split *s);
+
/* This routine makes a 'duplicate' of the indicated transaction.
* This routine cannot be exposed publically since the duplicate
* is wrong in many ways: it is not issued a unique guid, and thus
More information about the gnucash-changes
mailing list