[patch 4/4] several changes to Account and Group

c.shoemaker at cox.net c.shoemaker at cox.net
Fri Jul 22 14:16:32 EDT 2005


  - [N.B.] a change to the time comparision from > to >= in
xaccAccountGetBalanceAsOfDate()

  - increase use of glib

  - line wrap fixes

  - introduce xaccAccountGetXxxBalanceAsOfDateInCurrency() as a
natural extension of similar functions

  - comment fixups

 Account.c |  152 ++++++++++++++++++++++++++++++++++++++++++++++++--------------
 Account.h |   40 +++++++++++++---
 Group.c   |    5 --
 Group.h   |   21 ++++----
 4 files changed, 165 insertions(+), 53 deletions(-)

Index: gnucash/src/engine/Account.c
===================================================================
--- gnucash.orig/src/engine/Account.c
+++ gnucash/src/engine/Account.c
@@ -633,6 +633,7 @@ xaccAccountEqual(Account *aa, Account *a
 static gint
 split_sort_func(gconstpointer a, gconstpointer b) {
   /* don't coerce xaccSplitDateOrder so we'll catch changes */
+  /* huh?  what changes? */
   Split *sa = (Split *) a;
   Split *sb = (Split *) b;
   return(xaccSplitDateOrder(sa, sb));
@@ -1062,7 +1063,9 @@ xaccAccountSetStartingBalance(Account *a
  *                                                                  *
  * Return: int -- non-zero if out of order                          *
 \********************************************************************/
-
+/* CAS: Umm, we say we're checking the split, but we're actually
+   resorting all the splits.  Why not just leave the split out of
+   it? */
 void
 xaccAccountFixSplitDateOrder (Account * acc, Split *split) 
 {
@@ -1684,6 +1687,14 @@ xaccAccountGetBalanceAsOfDate (Account *
   /* Since transaction post times are stored as a Timespec,
    * convert date into a Timespec as well rather than converting
    * each transaction's Timespec into a time_t.
+   *
+   * FIXME: CAS: I think this comment is a bogus justification for
+   * using xaccTransGetDatePostedTS.  There's no benefit to using
+   * Timespec when the input argument is time_t, and it's hard to
+   * imagine that casting long long to long and comparing two longs is
+   * worse than comparing two long longs every time.  IMO,
+   * xaccAccountGetPresentBalance gets this right, and its algorithm
+   * should be used here.
    */
   ts.tv_sec = date;
   ts.tv_nsec = 0;
@@ -1693,7 +1704,7 @@ xaccAccountGetBalanceAsOfDate (Account *
   {
     xaccTransGetDatePostedTS( xaccSplitGetParent( (Split *)lp->data ),
                               &trans_ts );
-    if( timespec_cmp( &trans_ts, &ts ) > 0 )
+    if( timespec_cmp( &trans_ts, &ts ) >= 0 )
       found = TRUE;
     else
       lp = lp->next;
@@ -1733,8 +1744,7 @@ xaccAccountGetPresentBalance (Account *a
   GList *node;
   time_t today;
 
-  if (!account)
-    return gnc_numeric_zero ();
+  g_return_val_if_fail(account, gnc_numeric_zero());
 
   today = gnc_timet_get_today_end();
   for (node = g_list_last (account->splits); node; node = node->prev)
@@ -1774,7 +1784,8 @@ xaccAccountConvertBalanceToCurrency(Acco
   book = xaccGroupGetBook (xaccAccountGetRoot (account));
   pdb = gnc_pricedb_get_db (book);
 
-  balance = gnc_pricedb_convert_balance_latest_price(pdb, balance, balance_currency, new_currency);
+  balance = gnc_pricedb_convert_balance_latest_price(
+      pdb, balance, balance_currency, new_currency);
 
   return balance;
 }
@@ -1804,7 +1815,8 @@ xaccAccountConvertBalanceToCurrencyAsOfD
   ts.tv_sec = date;
   ts.tv_nsec = 0;
 
-  balance = gnc_pricedb_convert_balance_nearest_price(pdb, balance, balance_currency, new_currency, ts);
+  balance = gnc_pricedb_convert_balance_nearest_price(
+      pdb, balance, balance_currency, new_currency, ts);
 
   return balance;
 }
@@ -1824,11 +1836,22 @@ xaccAccountGetXxxBalanceInCurrency (Acco
   if (!account || !fn || !report_currency) return gnc_numeric_zero ();
   balance = fn(account);
   balance = xaccAccountConvertBalanceToCurrency(account, balance,
-					     account->commodity,
-					     report_currency);
+                                                account->commodity,
+                                                report_currency);
   return balance;
 }
 
+static gnc_numeric
+xaccAccountGetXxxBalanceAsOfDateInCurrency(Account *account, time_t date,
+                                           xaccGetBalanceAsOfDateFn fn,
+                                           gnc_commodity *report_commodity)
+{
+    g_return_val_if_fail(account && fn && report_commodity,
+                         gnc_numeric_zero());
+    return xaccAccountConvertBalanceToCurrency(
+        account, fn(account, date), account->commodity, report_commodity);
+}
+
 /*
  * Data structure used to pass various arguments into the following fn.
  */
@@ -1837,6 +1860,8 @@ typedef struct
   gnc_commodity *currency;
   gnc_numeric balance;
   xaccGetBalanceFn fn;
+  xaccGetBalanceAsOfDateFn asOfDateFn;
+  time_t date;
 } CurrencyBalance;
 
 
@@ -1859,13 +1884,33 @@ xaccAccountBalanceHelper (Account *accou
                                  GNC_HOW_RND_ROUND);
   return NULL;
 }
+static gpointer
+xaccAccountBalanceAsOfDateHelper (Account *account, gpointer data)
+{
+    CurrencyBalance *cb = data;
+    gnc_numeric balance;
+
+    g_return_val_if_fail (cb->asOfDateFn && cb->currency, NULL);
+
+    balance = xaccAccountGetXxxBalanceAsOfDateInCurrency (
+        account, cb->date, cb->asOfDateFn, cb->currency);
+    cb->balance = gnc_numeric_add (cb->balance, balance,
+                                   gnc_commodity_get_fraction (cb->currency),
+                                   GNC_HOW_RND_ROUND);
+    return NULL;
+}
+
+
 
 /*
  * Common function that iterates recursively over all accounts below
- * the specified account.  It uses the previous routine to sum up the
- * balances of all its children, and uses the specified function for
- * extracting the balance.  This function may extract the current
- * value, the reconciled value, etc.
+ * the specified account.  It uses xaccAccountBalanceHelper to sum up
+ * the balances of all its children, and uses the specified function
+ * 'fn' for extracting the balance.  This function may extract the
+ * current value, the reconciled value, etc.
+ *
+ * If 'report_commodity' is NULL, just use the account's commodity.
+ * If 'include_children' is FALSE, this function doesn't recurse at all.
  */
 static gnc_numeric
 xaccAccountGetXxxBalanceInCurrencyRecursive (Account *account,
@@ -1879,14 +1924,44 @@ xaccAccountGetXxxBalanceInCurrencyRecurs
     return gnc_numeric_zero ();
   if (!report_commodity)
     report_commodity = xaccAccountGetCommodity (account);
+
   balance = xaccAccountGetXxxBalanceInCurrency (account, fn, report_commodity);
 
-  /* If needed, sum up the children converting to *this* account's commodity. */
+  /* If needed, sum up the children converting to the *requested*
+     commodity. */
   if (include_children)
   {
-    CurrencyBalance cb = { report_commodity, balance, fn };
+    CurrencyBalance cb = { report_commodity, balance, fn, NULL, 0 };
 
-    xaccGroupForEachAccount (account->children, xaccAccountBalanceHelper, &cb, TRUE);
+    xaccGroupForEachAccount (account->children, xaccAccountBalanceHelper,
+                             &cb, TRUE);
+    balance = cb.balance;
+  }
+
+  return balance;
+}
+
+static gnc_numeric
+xaccAccountGetXxxBalanceAsOfDateInCurrencyRecursive (
+    Account *account, time_t date, xaccGetBalanceAsOfDateFn fn,
+    gnc_commodity *report_commodity, gboolean include_children)
+{
+  gnc_numeric balance;
+
+  g_return_val_if_fail(account, gnc_numeric_zero());
+  if (!report_commodity)
+      report_commodity = xaccAccountGetCommodity (account);
+
+  balance = xaccAccountGetXxxBalanceAsOfDateInCurrency(
+      account, date, fn, report_commodity);
+
+  /* If needed, sum up the children converting to the *requested*
+     commodity. */
+  if (include_children) {
+    CurrencyBalance cb = { report_commodity, balance, NULL, fn, date };
+
+    xaccGroupForEachAccount (account->children,
+                             xaccAccountBalanceAsOfDateHelper, &cb, TRUE);
     balance = cb.balance;
   }
 
@@ -1899,9 +1974,8 @@ xaccAccountGetBalanceInCurrency (Account
 				 gboolean include_children)
 {
   gnc_numeric rc;
-  rc = xaccAccountGetXxxBalanceInCurrencyRecursive (account, 
-                   xaccAccountGetBalance,
-						 report_commodity, include_children);
+  rc = xaccAccountGetXxxBalanceInCurrencyRecursive (
+      account, xaccAccountGetBalance, report_commodity, include_children);
   PINFO (" baln=%lld/%lld", rc.num, rc.denom);
   return rc;
 }
@@ -1912,9 +1986,9 @@ xaccAccountGetClearedBalanceInCurrency (
 					gnc_commodity *report_commodity,
 					gboolean include_children)
 {
-  return
-    xaccAccountGetXxxBalanceInCurrencyRecursive (account, xaccAccountGetClearedBalance,
-						 report_commodity, include_children);
+  return xaccAccountGetXxxBalanceInCurrencyRecursive (
+      account, xaccAccountGetClearedBalance, report_commodity,
+      include_children);
 }
 
 
@@ -1923,9 +1997,9 @@ xaccAccountGetReconciledBalanceInCurrenc
 				 gnc_commodity *report_commodity,
 				 gboolean include_children)
 {
-  return
-    xaccAccountGetXxxBalanceInCurrencyRecursive (account, xaccAccountGetReconciledBalance,
-						 report_commodity, include_children);
+  return xaccAccountGetXxxBalanceInCurrencyRecursive (
+      account, xaccAccountGetReconciledBalance, report_commodity,
+      include_children);
 }
 
 gnc_numeric
@@ -1933,19 +2007,29 @@ xaccAccountGetPresentBalanceInCurrency (
 					gnc_commodity *report_commodity,
 					gboolean include_children)
 {
-  return
-    xaccAccountGetXxxBalanceInCurrencyRecursive (account, xaccAccountGetPresentBalance,
-						 report_commodity, include_children);
+  return xaccAccountGetXxxBalanceInCurrencyRecursive (
+      account, xaccAccountGetPresentBalance, report_commodity,
+      include_children);
+}
+
+gnc_numeric
+xaccAccountGetProjectedMinimumBalanceInCurrency (
+    Account *account, gnc_commodity *report_commodity,
+    gboolean include_children)
+{
+  return xaccAccountGetXxxBalanceInCurrencyRecursive (
+      account, xaccAccountGetProjectedMinimumBalance, report_commodity,
+      include_children);
 }
 
 gnc_numeric
-xaccAccountGetProjectedMinimumBalanceInCurrency (Account *account,
-						 gnc_commodity *report_commodity,
-						 gboolean include_children)
-{
-  return
-    xaccAccountGetXxxBalanceInCurrencyRecursive (account, xaccAccountGetProjectedMinimumBalance,
-						 report_commodity, include_children);
+xaccAccountGetBalanceAsOfDateInCurrency(
+    Account *account, time_t date, gnc_commodity *report_commodity,
+    gboolean include_children)
+{
+    return xaccAccountGetXxxBalanceAsOfDateInCurrencyRecursive (
+        account, date, xaccAccountGetBalanceAsOfDate, report_commodity,
+        include_children);
 }
 
 /********************************************************************\
Index: gnucash/src/engine/Account.h
===================================================================
--- gnucash.orig/src/engine/Account.h
+++ gnucash/src/engine/Account.h
@@ -55,9 +55,13 @@
 
 
 typedef gnc_numeric (*xaccGetBalanceFn)( Account *account );
-typedef gnc_numeric (*xaccGetBalanceInCurrencyFn) (Account *account,
-						   gnc_commodity *report_commodity,
-						   gboolean include_children);
+
+typedef gnc_numeric (*xaccGetBalanceInCurrencyFn) (
+    Account *account, gnc_commodity *report_commodity,
+    gboolean include_children);
+
+typedef gnc_numeric (*xaccGetBalanceAsOfDateFn) (
+    Account *account, time_t date);
 
 #define GNC_IS_ACCOUNT(obj)  (QOF_CHECK_TYPE((obj), GNC_ID_ACCOUNT))
 #define GNC_ACCOUNT(obj)     (QOF_CHECK_CAST((obj), GNC_ID_ACCOUNT, Account))
@@ -311,7 +315,7 @@ gnc_commodity * xaccAccountGetCommodity 
 #define DxaccAccountGetSecurity xaccAccountGetCommodity
 
 /** Return the SCU for the account.  If a non-standard SCU has been
- *   set for the account, that s returned; else the default SCU for 
+ *   set for the account, that is returned; else the default SCU for
  *   the account commodity is returned.
  */
 int  xaccAccountGetCommoditySCU (Account *account);
@@ -341,7 +345,7 @@ gboolean  xaccAccountGetNonStdSCU (Accou
 /** @name Account Balance
  @{
 */
-/** Get the current balance of the account */
+/** Get the current balance of the account, which may include future splits */
 gnc_numeric     xaccAccountGetBalance (Account *account);
 /** Get the current balance of the account, only including cleared transactions */
 gnc_numeric     xaccAccountGetClearedBalance (Account *account);
@@ -352,6 +356,15 @@ gnc_numeric     xaccAccountGetProjectedM
 /** Get the balance of the account as of the date specified */
 gnc_numeric     xaccAccountGetBalanceAsOfDate (Account *account, time_t date);
 
+/* These two functions convert a given balance from one commodity to
+   another.  The account argument is only used to get the Book, and
+   may have nothing to do with the supplied balance.  Likewise, the
+   date argument is only used for commodity conversion and may have
+   nothing to do with supplied balance.
+
+   Since they really have nothing to do with Accounts, there's
+   probably some better place for them, but where?  gnc-commodity.h?
+*/
 gnc_numeric xaccAccountConvertBalanceToCurrency(Account *account, /* for book */
 						gnc_numeric balance,
 						gnc_commodity *balance_currency,
@@ -362,6 +375,8 @@ gnc_numeric xaccAccountConvertBalanceToC
 							gnc_commodity *new_currency,
 							time_t date);
 
+/* These functions get some type of balance in the desired commodity.
+   'report_commodity' may be NULL to use the account's commodity. */
 gnc_numeric xaccAccountGetBalanceInCurrency (Account *account,
 					     gnc_commodity *report_commodity,
 					     gboolean include_children);
@@ -377,6 +392,12 @@ gnc_numeric xaccAccountGetPresentBalance
 gnc_numeric xaccAccountGetProjectedMinimumBalanceInCurrency (Account *account,
 							     gnc_commodity *report_commodity,
 							     gboolean include_children);
+
+/* This function gets the balance as of the given date in the desired
+   commodity. */
+gnc_numeric xaccAccountGetBalanceAsOfDateInCurrency(
+    Account *account, time_t date, gnc_commodity *report_commodity,
+    gboolean include_children);
 /** @} */
 
 /** @name Account Children and Parents. 
@@ -411,7 +432,7 @@ Account *      xaccAccountGetParentAccou
 
 /** This routine returns a flat list of all of the accounts
  * that are descendents of this account.  This includes not
- * only the the children, but the cheldren of the children, etc.
+ * only the the children, but the children of the children, etc.
  * This routine is equivalent to the nested calls
  * xaccGroupGetSubAccounts (xaccAccountGetChildren())
  *
@@ -646,7 +667,12 @@ gboolean        xaccAccountGetPlaceholde
 /** DOCUMENT ME! */
 void            xaccAccountSetPlaceholder (Account *account,
                                            gboolean option);
-/** DOCUMENT ME! */
+
+/** Returns PLACEHOLDER_NONE if account is NULL or neither account nor
+ *  any descendent of account is a placeholder.  If account is a
+ *  placeholder, returns PLACEHOLDER_THIS.  Otherwise, if any
+ *  descendant of account is a placeholder, return PLACEHOLDER_CHILD.
+ */
 GNCPlaceholderType xaccAccountGetDescendantPlaceholder (Account *account);
 /** @} */
 
Index: gnucash/src/engine/Group.c
===================================================================
--- gnucash.orig/src/engine/Group.c
+++ gnucash/src/engine/Group.c
@@ -394,7 +394,7 @@ xaccGroupGetNumSubAccounts (AccountGroup
 }
 
 /********************************************************************\
- * Get all of the accounts, including subaccounts                   *
+ * Recursively get all of the accounts, including subaccounts       *
 \********************************************************************/
 
 static void
@@ -765,7 +765,7 @@ xaccGroupInsertAccount (AccountGroup *gr
           *
           * Note also, we need to reparent the children to the new book as well.
           */
-         PWARN ("reparenting accounts accross books is not correctly supported\n");
+         PWARN ("reparenting accounts across books is not correctly supported\n");
 
          gnc_engine_gen_event (&acc->inst.entity, GNC_EVENT_DESTROY);
          col = qof_book_get_collection (grp->book, GNC_ID_ACCOUNT);
@@ -1017,7 +1017,6 @@ xaccGroupGetDepth (AccountGroup *grp)
 
 /********************************************************************\
 \********************************************************************/
-
 void
 xaccSplitsBeginStagedTransactionTraversals (GList *splits)
 {
Index: gnucash/src/engine/Group.h
===================================================================
--- gnucash.orig/src/engine/Group.h
+++ gnucash/src/engine/Group.h
@@ -273,19 +273,22 @@ typedef  gpointer (*AccountCallback)(Acc
       you are done with it.
 */
 AccountList *xaccGroupMapAccounts(AccountGroup *grp,
-                             AccountCallback,
-                             gpointer data);
+                                  AccountCallback func,
+                                  gpointer data);
 
 /** The xaccGroupForEachAccount() method will traverse the AccountGroup
  *    tree, calling 'func' on each account.   Traversal will stop when
- *    func returns a non-null value, and the routine wil return with that 
- *    value.  If 'deeply' is FALSE, then only the immediate children of 
+ *    func returns a non-null value, and the routine will return with that
+ *    value.  Therefore, this function will return null iff func returns
+ *    null for every account.
+ *
+ *    If 'deeply' is FALSE, then only the immediate children of
  *    the account will be traversed.  If TRUE, then the whole tree will
  *    be traversed.
  */
 
 gpointer xaccGroupForEachAccount (AccountGroup *grp,
-                                  AccountCallback,
+                                  AccountCallback func,
                                   gpointer data,
                                   gboolean deeply);
 
@@ -390,7 +393,7 @@ int xaccGroupStagedTransactionTraversal(
 
 int xaccAccountStagedTransactionTraversal(Account *a,
                                           unsigned int stage,
-                                          TransactionCallback,
+                                          TransactionCallback thunk,
                                           void *data);
 
 /** Traverse all of the transactions in the given account group.
@@ -416,12 +419,12 @@ int xaccAccountStagedTransactionTraversa
 
    Note that this routine is just a trivial wrapper for 
    
-   xaccGroupBeginStagedTransactionTraversals(grp);
-   xaccGroupStagedTransactionTraversal(grp, 42, cb, data);
+   xaccGroupBeginStagedTransactionTraversals(g);
+   xaccGroupStagedTransactionTraversal(g, 42, proc, data);
  */
 
 int xaccGroupForEachTransaction(AccountGroup *g, 
-                                TransactionCallback, void *data);
+                                TransactionCallback proc, void *data);
 
 /** @} */
 #endif /* XACC_ACCOUNT_GROUP_H */

--


More information about the gnucash-patches mailing list