r21182 - gnucash/trunk/src - Implement a balance for owners and show it on the owners view page

Geert Janssens gjanssens at code.gnucash.org
Sat Aug 13 11:33:42 EDT 2011


Author: gjanssens
Date: 2011-08-13 11:33:42 -0400 (Sat, 13 Aug 2011)
New Revision: 21182
Trac: http://svn.gnucash.org/trac/changeset/21182

Modified:
   gnucash/trunk/src/app-utils/gnc-ui-util.c
   gnucash/trunk/src/app-utils/gnc-ui-util.h
   gnucash/trunk/src/engine/gncOwner.c
   gnucash/trunk/src/engine/gncOwner.h
   gnucash/trunk/src/gnome-utils/gnc-tree-model-owner.c
   gnucash/trunk/src/gnome-utils/gnc-tree-model-owner.h
   gnucash/trunk/src/gnome-utils/gnc-tree-view-owner.c
Log:
Implement a balance for owners and show it on the owners view page
The Balance column is not visible by default, but can be activated
with the blue arrow in the top-right of the page.

Modified: gnucash/trunk/src/app-utils/gnc-ui-util.c
===================================================================
--- gnucash/trunk/src/app-utils/gnc-ui-util.c	2011-08-13 15:33:27 UTC (rev 21181)
+++ gnucash/trunk/src/app-utils/gnc-ui-util.c	2011-08-13 15:33:42 UTC (rev 21182)
@@ -455,6 +455,94 @@
     return balance;
 }
 
+/*
+ * This is a wrapper routine around an gncOwnerGetBalanceInCurrency
+ * function that handles additional needs of the gui.
+ *
+ * @param owner     The owner to retrieve data about.
+ * @param negative  An indication of whether or not the returned value
+ *                  is negative.  This can be used by the caller to
+ *                  easily decode whether or not to color the output.
+ * @param commodity The commodity in which the account balance should
+ *                  be returned. If NULL, the value will be returned in
+ *                  the commodity of the owner. This is normally used
+ *                  to specify a currency, which forces the conversion
+ *                  of things like stock account values from share
+ *                  values to an amount the requested currency.
+ */
+gnc_numeric
+gnc_ui_owner_get_balance_full (GncOwner *owner,
+                               gboolean *negative,
+                               const gnc_commodity *commodity)
+{
+    gnc_numeric balance;
+
+    if (!owner)
+        return gnc_numeric_zero ();
+
+    balance = gncOwnerGetBalanceInCurrency (owner, commodity);
+
+    /* reverse sign if needed */
+    if ((gncOwnerGetType (owner) == GNC_OWNER_CUSTOMER))
+        balance = gnc_numeric_neg (balance);
+
+    /* Record whether the balance is negative. */
+    if (negative)
+        *negative = gnc_numeric_negative_p (balance);
+
+    return balance;
+}
+
+
+/**
+ * Wrapper around gnc_ui_owner_get_balance_full that converts
+ * the resulting number to a character string.  The number is
+ * formatted according to the specification of the owner currency.
+ * The caller is responsible for g_free'ing the returned memory.
+ *
+ * @param owner   The owner to retrieve data about.
+ * @param negative  An indication of whether or not the returned value
+ *                  is negative.  This can be used by the caller to
+ *                  easily decode whether or not to color the output.
+ */
+gchar *
+gnc_ui_owner_get_print_balance (GncOwner *owner,
+                                gboolean *negative)
+{
+    gnc_numeric balance;
+    GNCPrintAmountInfo print_info;
+
+    balance = gnc_ui_owner_get_balance_full (owner, negative, NULL);
+    print_info = gnc_commodity_print_info (gncOwnerGetCurrency (owner), TRUE);
+    return g_strdup (xaccPrintAmount (balance, print_info));
+}
+
+/**
+ * Wrapper around gnc_ui_owner_get_balance_full that converts
+ * the resulting number to a character string.  The number is
+ * formatted according to the specification of the default reporting
+ * currency.
+ *
+ * @param account   The owner to retrieve data about.
+ * @param negative  An indication of whether or not the returned value
+ *                  is negative.  This can be used by the caller to
+ *                  easily decode whether or not to color the output.
+ */
+gchar *
+gnc_ui_owner_get_print_report_balance (GncOwner *owner,
+                                       gboolean *negative)
+{
+    GNCPrintAmountInfo print_info;
+    gnc_numeric balance;
+    gnc_commodity *report_commodity;
+
+    report_commodity = gnc_default_report_currency ();
+    balance = gnc_ui_owner_get_balance_full (owner, negative,
+                                               report_commodity);
+    print_info = gnc_commodity_print_info (report_commodity, TRUE);
+    return g_strdup (xaccPrintAmount (balance, print_info));
+}
+
 /* Caller is responsible for g_free'ing returned memory */
 char *
 gnc_ui_account_get_tax_info_string (const Account *account)

Modified: gnucash/trunk/src/app-utils/gnc-ui-util.h
===================================================================
--- gnucash/trunk/src/app-utils/gnc-ui-util.h	2011-08-13 15:33:27 UTC (rev 21181)
+++ gnucash/trunk/src/app-utils/gnc-ui-util.h	2011-08-13 15:33:42 UTC (rev 21182)
@@ -36,6 +36,7 @@
 #include <locale.h>
 
 #include "Account.h"
+#include "gncOwner.h"
 #include "qof.h"
 
 
@@ -175,6 +176,33 @@
         gboolean recurse,
         gboolean *negative);
 
+/** Get the balance for the underlying owner object.
+ *  The returned value is always positive,
+ *  intended to be displayed to a user. However the real sign
+ *  of the balance is indicated via the "negative" parameter.
+ */
+gnc_numeric gnc_ui_owner_get_balance_full (GncOwner *owner,
+                                           gboolean *negative,
+                                           const gnc_commodity *commodity);
+
+/** Get the balance for the underlying owner object in string format
+ *  and the owner's native currency.
+ *  The returned value is always positive,
+ *  intended to be displayed to a user. However the real sign
+ *  of the balance is indicated via the "negative" parameter.
+ */
+gchar * gnc_ui_owner_get_print_balance (GncOwner *owner,
+                                        gboolean *negative);
+
+/** Get the balance for the underlying owner object in string format
+ *  and in the default report currency.
+ *  The returned value is always positive,
+ *  intended to be displayed to a user. However the real sign
+ *  of the balance is indicated via the "negative" parameter.
+ */
+gchar * gnc_ui_owner_get_print_report_balance (GncOwner *owner,
+                                               gboolean *negative);
+
 char *gnc_ui_account_get_tax_info_string (const Account *account);
 
 char *gnc_ui_account_get_tax_info_sub_acct_string (const Account *account);

Modified: gnucash/trunk/src/engine/gncOwner.c
===================================================================
--- gnucash/trunk/src/engine/gncOwner.c	2011-08-13 15:33:27 UTC (rev 21181)
+++ gnucash/trunk/src/engine/gncOwner.c	2011-08-13 15:33:42 UTC (rev 21182)
@@ -1006,6 +1006,69 @@
     return (g_list_prepend (NULL, gncOwnerGetCurrency(owner)));
 }
 
+/*********************************************************************/
+/* Owner balance calculation routines                                */
+
+/*
+ * Given an owner, extract the open balance from the owner and then
+ * convert it to the desired currency.
+ */
+gnc_numeric
+gncOwnerGetBalanceInCurrency (GncOwner *owner,
+                              const gnc_commodity *report_currency)
+{
+    gnc_numeric balance = gnc_numeric_zero ();
+    GList *acct_list, *acct_node, *acct_types, *lot_list = NULL, *lot_node;
+    QofBook *book;
+    gnc_commodity *owner_currency;
+    GNCPriceDB *pdb;
+
+    g_return_val_if_fail (owner, gnc_numeric_zero ());
+
+    /* Get account list */
+    book       = qof_instance_get_book (qofOwnerGetOwner (owner));
+    acct_list  = gnc_account_get_descendants (gnc_book_get_root_account (book));
+    acct_types = gncOwnerGetAccountTypesList (owner);
+    owner_currency = gncOwnerGetCurrency (owner);
+
+    /* For each account */
+    for (acct_node = acct_list; acct_node; acct_node = acct_node->next)
+    {
+        Account *account = acct_node->data;
+
+        /* Check if this account can have lots for the owner, otherwise skip to next */
+        if (g_list_index (acct_types, (gpointer)xaccAccountGetType (account))
+                == -1)
+            continue;
+
+
+        if (!gnc_commodity_equal (owner_currency, xaccAccountGetCommodity (account)))
+            continue;
+
+        /* Get a list of open lots for this owner and account */
+        lot_list = xaccAccountFindOpenLots (account, gnc_lot_match_invoice_owner,
+                                            owner,
+                                            (GCompareFunc)gnc_lot_sort_func);
+        /* For each lot */
+        for (lot_node = lot_list; lot_node; lot_node = lot_node->next)
+        {
+            GNCLot *lot = lot_node->data;
+            gnc_numeric lot_balance = gnc_lot_get_balance (lot);
+            balance = gnc_numeric_add (balance, lot_balance,
+                      gnc_commodity_get_fraction (owner_currency), GNC_HOW_RND_ROUND_HALF_UP);
+        }
+    }
+
+    pdb = gnc_pricedb_get_db (book);
+
+    if (report_currency)
+        balance = gnc_pricedb_convert_balance_latest_price (
+                      pdb, balance, owner_currency, report_currency);
+
+    return balance;
+}
+
+
 /* XXX: Yea, this is broken, but it should work fine for Queries.
  * We're single-threaded, right?
  */

Modified: gnucash/trunk/src/engine/gncOwner.h
===================================================================
--- gnucash/trunk/src/engine/gncOwner.h	2011-08-13 15:33:27 UTC (rev 21181)
+++ gnucash/trunk/src/engine/gncOwner.h	2011-08-13 15:33:42 UTC (rev 21182)
@@ -192,6 +192,14 @@
 /** Returns a GList of currencies associated with the owner */
 GList * gncOwnerGetCommoditiesList (const GncOwner *owner);
 
+
+/** Given an owner, extract the open balance from the owner and then
+ *  convert it to the desired currency.
+ */
+gnc_numeric
+gncOwnerGetBalanceInCurrency (GncOwner *owner,
+                              const gnc_commodity *report_currency);
+
 #define OWNER_TYPE        "type"
 #define OWNER_TYPE_STRING "type-string"  /**< Allows the type to be handled externally. */
 #define OWNER_CUSTOMER    "customer"

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-model-owner.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-model-owner.c	2011-08-13 15:33:27 UTC (rev 21181)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-model-owner.c	2011-08-13 15:33:42 UTC (rev 21182)
@@ -405,11 +405,9 @@
     case GNC_TREE_MODEL_OWNER_COL_EMAIL:
     case GNC_TREE_MODEL_OWNER_COL_BALANCE:
     case GNC_TREE_MODEL_OWNER_COL_BALANCE_REPORT:
-    case GNC_TREE_MODEL_OWNER_COL_BALANCE_PERIOD:
     case GNC_TREE_MODEL_OWNER_COL_NOTES:
 
     case GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE:
-    case GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE_PERIOD:
         return G_TYPE_STRING;
 
     case GNC_TREE_MODEL_OWNER_COL_ACTIVE:
@@ -526,43 +524,6 @@
         g_value_set_static_string (value, "black");
 }
 
-static gchar *
-gnc_tree_model_owner_compute_period_balance(GncTreeModelOwner *model,
-        GncOwner *acct,
-        gboolean recurse,
-        gboolean *negative)
-{
-    GncTreeModelOwnerPrivate *priv;
-    time_t t1, t2;
-    gnc_numeric b3;
-
-    if ( negative )
-        *negative = FALSE;
-
-    /* FIXME Figure out how to calculate the payment balance for an owner.
-     *       The code below is from the account tree model and should be
-     *       adapted for owners.
-    priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model);
-    if (acct == priv->root)
-        return g_strdup("");
-
-    t1 = gnc_ownering_period_fiscal_start();
-    t2 = gnc_ownering_period_fiscal_end();
-
-    if (t1 > t2)
-        return g_strdup("");
-
-    b3 = xaccOwnerGetBalanceChangeForPeriod(acct, t1, t2, recurse);
-    if (gnc_reverse_balance (acct))
-        b3 = gnc_numeric_neg (b3);
-
-    if (negative)
-        *negative = gnc_numeric_negative_p(b3);
-
-    return g_strdup(xaccPrintAmount(b3, gnc_owner_print_info(acct, TRUE))); */
-    return g_strdup("0");
-}
-
 static void
 gnc_tree_model_owner_get_value (GtkTreeModel *tree_model,
                                 GtkTreeIter *iter,
@@ -674,40 +635,21 @@
 
     case GNC_TREE_MODEL_OWNER_COL_BALANCE:
         g_value_init (value, G_TYPE_STRING);
-        /* FIXME how to calculate an Owner's balance ?
-        string = gnc_ui_owner_get_print_balance(xaccOwnerGetBalanceInCurrency,
-                 owner, TRUE, &negative);
-        g_value_take_string (value, string); */
-        g_value_set_static_string (value, "0");
+        string = gnc_ui_owner_get_print_balance(owner, &negative);
+        g_value_take_string (value, string);
         break;
+
     case GNC_TREE_MODEL_OWNER_COL_BALANCE_REPORT:
         g_value_init (value, G_TYPE_STRING);
-        /* FIXME how to calculate an Owner's balance ?
-        string = gnc_ui_owner_get_print_report_balance(xaccOwnerGetBalanceInCurrency,
-                 owner, TRUE, &negative);
-        g_value_take_string (value, string); */
-        g_value_set_static_string (value, "0");
+        string = gnc_ui_owner_get_print_report_balance(owner, &negative);
+        g_value_take_string (value, string);
         break;
     case GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE:
         g_value_init (value, G_TYPE_STRING);
-        /* FIXME how to calculate an Owner's balance ?
-        string = gnc_ui_owner_get_print_balance(xaccOwnerGetBalanceInCurrency,
-                 owner, TRUE, &negative);*/
-        negative = FALSE;
+        string = gnc_ui_owner_get_print_balance(owner, &negative);
         gnc_tree_model_owner_set_color(model, negative, value);
-        /* g_free(string);*/
+        g_free(string);
         break;
-    case GNC_TREE_MODEL_OWNER_COL_BALANCE_PERIOD:
-        g_value_init (value, G_TYPE_STRING);
-        string = gnc_tree_model_owner_compute_period_balance(model, owner, FALSE, &negative);
-        g_value_take_string (value, string);
-        break;
-    case GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE_PERIOD:
-        g_value_init (value, G_TYPE_STRING);
-        string = gnc_tree_model_owner_compute_period_balance(model, owner, FALSE, &negative);
-        gnc_tree_model_owner_set_color(model, negative, value);
-        g_free (string);
-        break;
 
     case GNC_TREE_MODEL_OWNER_COL_NOTES:
         g_value_init (value, G_TYPE_STRING);

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-model-owner.h
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-model-owner.h	2011-08-13 15:33:27 UTC (rev 21181)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-model-owner.h	2011-08-13 15:33:42 UTC (rev 21182)
@@ -67,7 +67,6 @@
     GNC_TREE_MODEL_OWNER_COL_EMAIL,
     GNC_TREE_MODEL_OWNER_COL_BALANCE,
     GNC_TREE_MODEL_OWNER_COL_BALANCE_REPORT,
-    GNC_TREE_MODEL_OWNER_COL_BALANCE_PERIOD,
     GNC_TREE_MODEL_OWNER_COL_NOTES,
     GNC_TREE_MODEL_OWNER_COL_ACTIVE,
 
@@ -75,7 +74,6 @@
 
     /* internal hidden columns */
     GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE,
-    GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE_PERIOD,
 
     GNC_TREE_MODEL_OWNER_NUM_COLUMNS
 } GncTreeModelOwnerColumn;

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-view-owner.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-view-owner.c	2011-08-13 15:33:27 UTC (rev 21181)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-view-owner.c	2011-08-13 15:33:42 UTC (rev 21182)
@@ -315,30 +315,20 @@
 }
 
 static gint
-sort_by_xxx_value (xaccGetBalanceInCurrencyFn fn,
-                   gboolean recurse,
-                   GtkTreeModel *f_model,
+sort_by_xxx_value (GtkTreeModel *f_model,
                    GtkTreeIter *f_iter_a,
                    GtkTreeIter *f_iter_b,
                    gpointer user_data)
 {
-    const GncOwner *owner_a, *owner_b;
+    GncOwner *owner_a, *owner_b;
     gnc_numeric balance_a, balance_b;
     gint result;
 
     /* Find the owners */
-    sort_cb_setup (f_model, f_iter_a, f_iter_b, &owner_a, &owner_b);
+    sort_cb_setup (f_model, f_iter_a, f_iter_b, (const GncOwner**)&owner_a, (const GncOwner**)&owner_b);
 
-    /* Get balances */
-    /* FIXME I'm not aware of any functions to get an owner's "balance" yet.
-     *       This should be implemented before this function does anything useful.
-     *       The code below is copied from the tree-view-account source to serve
-     *       as an example.
-    balance_a = gnc_ui_owner_get_balance_full(fn, owner_a, recurse, NULL, NULL);
-    balance_b = gnc_ui_owner_get_balance_full(fn, owner_b, recurse, NULL, NULL);
-    */
-    balance_a = gnc_numeric_zero();
-    balance_b = gnc_numeric_zero();
+    balance_a = gnc_ui_owner_get_balance_full(owner_a, NULL, NULL);
+    balance_b = gnc_ui_owner_get_balance_full(owner_b, NULL, NULL);
 
     result = gnc_numeric_compare(balance_a, balance_b);
     if (result != 0)
@@ -352,58 +342,10 @@
                        GtkTreeIter *f_iter_b,
                        gpointer user_data)
 {
-    /* FIXME I'm not aware of any functions to get an owner's "balance" yet.
-     *       This should be implemented before this function does anything useful.
-     *       The code below is copied from the tree-view-account source to serve
-     *       as an example.
-    return sort_by_xxx_value (gncOwnerGetBalanceInCurrency, TRUE,
-                              f_model, f_iter_a, f_iter_b, user_data);
-     */
-     return sort_by_xxx_value (NULL, TRUE,
-             f_model, f_iter_a, f_iter_b, user_data);
+    return sort_by_xxx_value (f_model, f_iter_a, f_iter_b, user_data);
 }
-static gint
-sort_by_xxx_period_value (GtkTreeModel *f_model,
-                          GtkTreeIter *f_iter_a,
-                          GtkTreeIter *f_iter_b,
-                          gboolean recurse)
-{
-    GncOwner *owner1, *owner2;
-    time_t t1, t2;
-    gnc_numeric b1, b2;
-    gint result;
 
-    sort_cb_setup (f_model, f_iter_a, f_iter_b,
-                   (const GncOwner **)&owner1, (const GncOwner **)&owner2);
 
-    t1 = gnc_accounting_period_fiscal_start();
-    t2 = gnc_accounting_period_fiscal_end();
-
-    /* FIXME I'm not aware of any functions to get an owner's "balance" yet.
-     *       This should be implemented before this function does anything useful.
-     *       The code below is copied from the tree-view-account source to serve
-     *       as an example.
-    b1 = gncOwnerGetBalanceChangeForPeriod(owner1, t1, t2, recurse);
-    b2 = gncOwnerGetBalanceChangeForPeriod(owner2, t1, t2, recurse);
-    */
-    b1 = gnc_numeric_zero();
-    b2 = gnc_numeric_zero();
-
-    result = gnc_numeric_compare(b1, b2);
-    if (result != 0)
-        return result;
-    return gncOwnerCompare(owner1, owner2);
-}
-
-static gint
-sort_by_balance_period_value (GtkTreeModel *f_model,
-                              GtkTreeIter *f_iter_a,
-                              GtkTreeIter *f_iter_b,
-                              gpointer user_data)
-{
-    return sort_by_xxx_period_value (f_model, f_iter_a, f_iter_b, FALSE);
-}
-
 /************************************************************/
 /*                    New View Creation                     */
 /************************************************************/
@@ -520,20 +462,15 @@
                                      GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE,
                                      GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
                                      sort_by_balance_value);
+
     priv->balance_report_column
-    = gnc_tree_view_add_numeric_column(view, _("Balance (Report)"), GNC_OWNER_TREE_BALANCE_REPORT_COL,
+    = gnc_tree_view_add_numeric_column(view, _("Balance"), GNC_OWNER_TREE_BALANCE_REPORT_COL,
                                        SAMPLE_OWNER_VALUE,
                                        GNC_TREE_MODEL_OWNER_COL_BALANCE_REPORT,
                                        GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE,
                                        GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
                                        sort_by_balance_value);
 
-    gnc_tree_view_add_numeric_column(view, _("Balance (Period)"), GNC_OWNER_TREE_BALANCE_PERIOD_COL,
-                                     SAMPLE_OWNER_VALUE,
-                                     GNC_TREE_MODEL_OWNER_COL_BALANCE_PERIOD,
-                                     GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE_PERIOD,
-                                     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
-                                     sort_by_balance_period_value);
     priv->notes_column
     = gnc_tree_view_add_text_column(view, _("Notes"), GNC_OWNER_TREE_NOTES_COL, NULL,
                                     "Sample owner notes.",



More information about the gnucash-changes mailing list