gnucash master: Multiple changes pushed
John Ralls
jralls at code.gnucash.org
Fri Dec 30 19:12:33 EST 2022
Updated via https://github.com/Gnucash/gnucash/commit/31d79e30 (commit)
via https://github.com/Gnucash/gnucash/commit/7536fcaf (commit)
via https://github.com/Gnucash/gnucash/commit/3be25ff0 (commit)
via https://github.com/Gnucash/gnucash/commit/a15c6f81 (commit)
via https://github.com/Gnucash/gnucash/commit/841b0694 (commit)
via https://github.com/Gnucash/gnucash/commit/60ab654d (commit)
via https://github.com/Gnucash/gnucash/commit/5108c52e (commit)
via https://github.com/Gnucash/gnucash/commit/fb84cf7d (commit)
via https://github.com/Gnucash/gnucash/commit/518ecfe0 (commit)
from https://github.com/Gnucash/gnucash/commit/a7abb82d (commit)
commit 31d79e30042fdb843e4b11a24c2aef53c7fc691a
Merge: a7abb82d3 7536fcaf2
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Dec 30 16:00:12 2022 -0800
Merge Bob Fewell's 'bug798673' into master.
commit 7536fcaf2f1521f65b9f1bbf041d172cc66cadfe
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Fri Dec 16 15:17:49 2022 +0000
Change the balance limit icon if both limits are zero
When higher and lower limits are zero, when used for a a suspense
account, change the icon to 'dialog-warning'. This type of use is to
indicate that a non zero balance exists.
diff --git a/gnucash/gnome-utils/gnc-tree-model-account.c b/gnucash/gnome-utils/gnc-tree-model-account.c
index 7f083c434..4da356212 100644
--- a/gnucash/gnome-utils/gnc-tree-model-account.c
+++ b/gnucash/gnome-utils/gnc-tree-model-account.c
@@ -833,12 +833,7 @@ gnc_tree_model_account_get_value (GtkTreeModel *tree_model,
case GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_LIMIT:
g_value_init (value, G_TYPE_STRING);
- if (gnc_ui_account_is_higher_balance_limit_reached (account))
- string = "go-top";
- else if (gnc_ui_account_is_lower_balance_limit_reached (account))
- string = "go-bottom";
- else
- string = "";
+ string = gnc_ui_account_get_balance_limit_icon_name (account);
g_value_set_string (value, string);
break;
diff --git a/libgnucash/app-utils/gnc-ui-balances.c b/libgnucash/app-utils/gnc-ui-balances.c
index 05539e7a8..3893c04e1 100644
--- a/libgnucash/app-utils/gnc-ui-balances.c
+++ b/libgnucash/app-utils/gnc-ui-balances.c
@@ -272,7 +272,8 @@ account_balance_limit_reached (const Account *account, gnc_numeric balance_limit
}
gboolean
-gnc_ui_account_is_higher_balance_limit_reached (const Account *account)
+gnc_ui_account_is_higher_balance_limit_reached (const Account *account,
+ gboolean *is_zero)
{
gnc_numeric balance_limit;
gboolean limit_valid = FALSE;
@@ -289,6 +290,9 @@ gnc_ui_account_is_higher_balance_limit_reached (const Account *account)
if (!limit_valid)
return retval;
+ if (gnc_numeric_zero_p (balance_limit))
+ *is_zero = TRUE;
+
if (account_balance_limit_reached (account, balance_limit) == 1)
retval = TRUE;
@@ -296,7 +300,8 @@ gnc_ui_account_is_higher_balance_limit_reached (const Account *account)
}
gboolean
-gnc_ui_account_is_lower_balance_limit_reached (const Account *account)
+gnc_ui_account_is_lower_balance_limit_reached (const Account *account,
+ gboolean *is_zero)
{
gnc_numeric balance_limit;
gboolean limit_valid = FALSE;
@@ -313,12 +318,44 @@ gnc_ui_account_is_lower_balance_limit_reached (const Account *account)
if (!limit_valid)
return retval;
+ if (gnc_numeric_zero_p (balance_limit))
+ *is_zero = TRUE;
+
if (account_balance_limit_reached (account, balance_limit) == -1)
retval = TRUE;
return retval;
}
+gchar *
+gnc_ui_account_get_balance_limit_icon_name (const Account *account)
+{
+ gboolean lower_limit_reached, higher_limit_reached;
+ gboolean lower_is_zero = FALSE;
+ gboolean higher_is_zero = FALSE;
+
+ g_return_val_if_fail (GNC_IS_ACCOUNT(account), g_strdup (""));
+
+ higher_limit_reached = gnc_ui_account_is_higher_balance_limit_reached (account, &higher_is_zero);
+
+ // assume the higher value will be set mostly so test that first
+ if (higher_limit_reached && !higher_is_zero)
+ return g_strdup ("go-top");
+
+ lower_limit_reached = gnc_ui_account_is_lower_balance_limit_reached (account, &lower_is_zero);
+
+ if (lower_limit_reached && (!lower_is_zero || !higher_is_zero))
+ return g_strdup ("go-bottom");
+
+ if (higher_limit_reached && !lower_is_zero)
+ return g_strdup ("go-top");
+
+ if ((lower_limit_reached || higher_limit_reached ) && lower_is_zero && higher_is_zero)
+ return g_strdup ("dialog-warning");
+
+ return g_strdup ("");
+}
+
/********************************************************************
* Balance calculations related to owners
********************************************************************/
diff --git a/libgnucash/app-utils/gnc-ui-balances.h b/libgnucash/app-utils/gnc-ui-balances.h
index 2cf0506de..f0b4d5516 100644
--- a/libgnucash/app-utils/gnc-ui-balances.h
+++ b/libgnucash/app-utils/gnc-ui-balances.h
@@ -160,18 +160,30 @@ GList * gnc_account_get_autoclear_splits (Account *account, gnc_numeric toclear_
*
* @param account A pointer to the account.
*
+ * @param is_zero A return value, set to TRUE if limit is zero
+ *
* @return TRUE if account balance has passed limit.
*/
-gboolean gnc_ui_account_is_higher_balance_limit_reached (const Account *account);
+gboolean gnc_ui_account_is_higher_balance_limit_reached (const Account *account, gboolean *is_zero);
/** Test the account balance as of today for it passing the
* lower limit if set.
*
* @param account A pointer to the account.
*
+ * @param is_zero A return value, set to TRUE if limit is zero
+ *
* @return TRUE if account balance has passed limit.
*/
-gboolean gnc_ui_account_is_lower_balance_limit_reached (const Account *account);
+gboolean gnc_ui_account_is_lower_balance_limit_reached (const Account *account, gboolean *is_zero);
+/** Test the account balance as of today for it passing the
+ * lower and higher limits if set.
+ *
+ * @param account A pointer to the account.
+ *
+ * @return The icon name to be displayed.
+ */
+gchar * gnc_ui_account_get_balance_limit_icon_name (const Account *account);
#endif /* GNC_UI_BALANCES_H_ */
commit 3be25ff0a9c53878eeffa2d065c6da06999833e5
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Tue Dec 13 11:48:05 2022 +0000
Add some tests for the account functions
diff --git a/libgnucash/engine/test/utest-Account.cpp b/libgnucash/engine/test/utest-Account.cpp
index 093bc60a9..60fb3888b 100644
--- a/libgnucash/engine/test/utest-Account.cpp
+++ b/libgnucash/engine/test/utest-Account.cpp
@@ -1089,6 +1089,9 @@ test_gnc_account_kvp_setters_getters (Fixture *fixture, gconstpointer pData)
{
Account *account = xaccMallocAccount (gnc_account_get_book (fixture->acct));
xaccAccountSetType (account, ACCT_TYPE_EQUITY);
+ gnc_numeric h_balance = gnc_numeric_create (1700, 100);
+ gnc_numeric l_balance = gnc_numeric_create (1000, 100);
+ gnc_numeric balance_limit;
// equity_type getter/setter
g_assert (xaccAccountGetIsOpeningBalance (account) == FALSE);
@@ -1231,6 +1234,32 @@ test_gnc_account_kvp_setters_getters (Fixture *fixture, gconstpointer pData)
xaccAccountSetNotes (account, nullptr);
g_assert_cmpstr (xaccAccountGetNotes (account), ==, nullptr);
+ // Balance Limits getter/setter
+ g_assert (xaccAccountGetHigherBalanceLimit (account, &balance_limit) == false);
+ g_assert (xaccAccountGetLowerBalanceLimit (account, &balance_limit) == false);
+ g_assert (xaccAccountGetIncludeSubAccountBalances (account) == false);
+
+ xaccAccountSetHigherBalanceLimit (account, h_balance);
+ xaccAccountSetLowerBalanceLimit (account, l_balance);
+ xaccAccountSetIncludeSubAccountBalances (account, true);
+
+ g_assert (xaccAccountGetHigherBalanceLimit (account, &balance_limit) == true);
+ g_assert_cmpint (gnc_numeric_compare (h_balance, balance_limit), ==, 0);
+
+ g_assert (xaccAccountGetLowerBalanceLimit (account, &balance_limit) == true);
+ g_assert_cmpint (gnc_numeric_compare (l_balance, balance_limit), ==, 0);
+
+ g_assert (xaccAccountGetIncludeSubAccountBalances (account) == true);
+
+ xaccAccountSetIncludeSubAccountBalances (account, false);
+
+ xaccAccountClearHigherBalanceLimit (account);
+ xaccAccountClearLowerBalanceLimit (account);
+
+ g_assert (xaccAccountGetHigherBalanceLimit (account, &balance_limit) == false);
+ g_assert (xaccAccountGetLowerBalanceLimit (account, &balance_limit) == false);
+ g_assert (xaccAccountGetIncludeSubAccountBalances (account) == false);
+
// STOCK_ACCOUNT tests from now on
xaccAccountSetType (account, ACCT_TYPE_STOCK);
commit a15c6f81b34cc84cecd09500d1d12839aad1ba41
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Tue Dec 13 11:47:30 2022 +0000
Allow the balances of sub accounts to be used in limits
diff --git a/gnucash/gnome-utils/dialog-account.c b/gnucash/gnome-utils/dialog-account.c
index be426f1b9..4043bc650 100644
--- a/gnucash/gnome-utils/dialog-account.c
+++ b/gnucash/gnome-utils/dialog-account.c
@@ -111,6 +111,7 @@ typedef struct _AccountWindow
GtkWidget *balance_grid;
GtkWidget *higher_balance_limit_edit;
GtkWidget *lower_balance_limit_edit;
+ GtkWidget *include_balance_sub_accts;
gboolean balance_is_reversed;
GtkWidget *opening_balance_button;
@@ -336,6 +337,11 @@ gnc_account_to_ui (AccountWindow *aw)
aw->balance_is_reversed = gnc_reverse_balance (account);
+ flag = xaccAccountGetIncludeSubAccountBalances (account);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(aw->include_balance_sub_accts),
+ flag);
+
balance_limit_valid = xaccAccountGetHigherBalanceLimit (account, &balance_limit);
if (balance_limit_valid)
{
@@ -433,7 +439,8 @@ gnc_ui_to_account (AccountWindow *aw)
gboolean flag;
gnc_numeric balance;
gnc_numeric balance_limit;
- gint balance_limit_valid;
+ gint higher_balance_limit_valid;
+ gint lower_balance_limit_valid;
gboolean use_equity, nonstd;
time64 date;
gint index, old_scu, new_scu;
@@ -546,10 +553,16 @@ gnc_ui_to_account (AccountWindow *aw)
if (parent_account != gnc_account_get_parent (account))
gnc_account_append_child (parent_account, account);
- balance_limit_valid = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT(aw->higher_balance_limit_edit),
- &balance_limit, TRUE, NULL);
+ flag = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(
+ aw->include_balance_sub_accts));
+
+ xaccAccountSetIncludeSubAccountBalances (account, flag);
+
+ higher_balance_limit_valid = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT(
+ aw->higher_balance_limit_edit),
+ &balance_limit, TRUE, NULL);
- if (balance_limit_valid == 0)
+ if (higher_balance_limit_valid == 0)
{
if (aw->balance_is_reversed)
{
@@ -560,7 +573,7 @@ gnc_ui_to_account (AccountWindow *aw)
xaccAccountSetHigherBalanceLimit (account, balance_limit);
}
- if (balance_limit_valid == -1)
+ if (higher_balance_limit_valid == -1)
{
if (aw->balance_is_reversed)
xaccAccountClearLowerBalanceLimit (account);
@@ -568,10 +581,11 @@ gnc_ui_to_account (AccountWindow *aw)
xaccAccountClearHigherBalanceLimit (account);
}
- balance_limit_valid = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT(aw->lower_balance_limit_edit),
- &balance_limit, TRUE, NULL);
+ lower_balance_limit_valid = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT(
+ aw->lower_balance_limit_edit),
+ &balance_limit, TRUE, NULL);
- if (balance_limit_valid == 0)
+ if (lower_balance_limit_valid == 0)
{
if (aw->balance_is_reversed)
{
@@ -582,7 +596,7 @@ gnc_ui_to_account (AccountWindow *aw)
xaccAccountSetLowerBalanceLimit (account, balance_limit);
}
- if (balance_limit_valid == -1)
+ if (lower_balance_limit_valid == -1)
{
if (aw->balance_is_reversed)
xaccAccountClearHigherBalanceLimit (account);
@@ -590,6 +604,9 @@ gnc_ui_to_account (AccountWindow *aw)
xaccAccountClearLowerBalanceLimit (account);
}
+ if ((higher_balance_limit_valid == -1) && (lower_balance_limit_valid == -1))
+ xaccAccountSetIncludeSubAccountBalances (account, FALSE);
+
xaccAccountCommitEdit (account);
balance = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT(aw->opening_balance_edit));
@@ -1618,6 +1635,8 @@ gnc_account_window_create (GtkWindow *parent, AccountWindow *aw)
gnc_amount_edit_show_warning_symbol (GNC_AMOUNT_EDIT(aw->lower_balance_limit_edit), TRUE);
gtk_widget_show (aw->lower_balance_limit_edit);
+ aw->include_balance_sub_accts = GTK_WIDGET(gtk_builder_get_object (builder, "include_sub_accts_tb"));
+
aw->more_properties_page =
gtk_notebook_get_nth_page (GTK_NOTEBOOK(aw->notebook), 1);
@@ -2103,14 +2122,6 @@ gnc_ui_edit_account_window (GtkWindow *parent, Account *account)
if (xaccAccountGetSplitList (account) != NULL)
gtk_widget_hide (aw->opening_balance_page);
- // Note: we are hiding the notebook page here, when other items
- // are added this will need adjusting.
- if (gnc_account_n_children (account) > 0)
- {
- gtk_widget_hide (GTK_WIDGET(aw->balance_grid));
- gtk_widget_hide (GTK_WIDGET(aw->more_properties_page));
- }
-
parent_acct = gnc_account_get_parent (account);
if (parent_acct == NULL)
parent_acct = account; // must be at the root
diff --git a/gnucash/gtkbuilder/dialog-account.glade b/gnucash/gtkbuilder/dialog-account.glade
index e81dc5c99..cf6f773ee 100644
--- a/gnucash/gtkbuilder/dialog-account.glade
+++ b/gnucash/gtkbuilder/dialog-account.glade
@@ -1691,7 +1691,7 @@
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<child>
- <!-- n-columns=2 n-rows=3 -->
+ <!-- n-columns=2 n-rows=4 -->
<object class="GtkGrid" id="balance_grid">
<property name="visible">True</property>
<property name="can-focus">False</property>
@@ -1783,6 +1783,23 @@ Clear the entry to have no warning.</property>
<property name="width">2</property>
</packing>
</child>
+ <child>
+ <object class="GtkCheckButton" id="include_sub_accts_tb">
+ <property name="label" translatable="yes">_Include sub accounts</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
</object>
<packing>
<property name="expand">False</property>
diff --git a/libgnucash/app-utils/gnc-ui-balances.c b/libgnucash/app-utils/gnc-ui-balances.c
index 222ba658a..05539e7a8 100644
--- a/libgnucash/app-utils/gnc-ui-balances.c
+++ b/libgnucash/app-utils/gnc-ui-balances.c
@@ -253,9 +253,13 @@ gnc_ui_account_get_reconciled_balance_as_of_date (Account *account,
static gint
account_balance_limit_reached (const Account *account, gnc_numeric balance_limit)
{
+ gboolean inc_sub = xaccAccountGetIncludeSubAccountBalances (account);
+
// we use today's date because account may have future dated splits
- gnc_numeric balance = xaccAccountGetBalanceAsOfDate ((Account*)account,
- gnc_time64_get_day_end (gnc_time (NULL)));
+ gnc_numeric balance = gnc_ui_account_get_balance_as_of_date (
+ (Account*)account,
+ gnc_time64_get_day_end (gnc_time (NULL)),
+ inc_sub);
if (gnc_numeric_zero_p (balance))
return 0;
diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp
index f6863a0ce..aad4791d2 100644
--- a/libgnucash/engine/Account.cpp
+++ b/libgnucash/engine/Account.cpp
@@ -76,6 +76,7 @@ static const std::string AB_TRANS_RETRIEVAL("trans-retrieval");
static const std::string KEY_BALANCE_LIMIT("balance-limit");
static const std::string KEY_BALANCE_HIGHER_LIMIT_VALUE("higher-value");
static const std::string KEY_BALANCE_LOWER_LIMIT_VALUE("lower-value");
+static const std::string KEY_BALANCE_INCLUDE_SUB_ACCTS("inlude-sub-accts");
static gnc_numeric GetBalanceAsOfDate (Account *acc, time64 date, gboolean ignclosing);
@@ -336,6 +337,7 @@ gnc_account_init(Account* acc)
priv->higher_balance_cached = false;
priv->lower_balance_limit = gnc_numeric_create (1,0);
priv->lower_balance_cached = false;
+ priv->include_sub_account_balances = TriState::Unset;
priv->last_num = (char*) is_unset;
priv->tax_us_code = (char*) is_unset;
@@ -5141,6 +5143,47 @@ xaccAccountClearLowerBalanceLimit (Account *acc)
clear_balance_limits (acc, false);
}
+gboolean
+xaccAccountGetIncludeSubAccountBalances (const Account *acc)
+{
+ g_return_val_if_fail (GNC_IS_ACCOUNT(acc), false);
+
+ if (GET_PRIVATE(acc)->include_sub_account_balances == TriState::Unset)
+ {
+ gboolean inc_sub = boolean_from_key (acc, {KEY_BALANCE_LIMIT,
+ KEY_BALANCE_INCLUDE_SUB_ACCTS});
+
+ GET_PRIVATE(acc)->include_sub_account_balances = inc_sub ? TriState::True
+ : TriState::False;
+ }
+ return GET_PRIVATE(acc)->include_sub_account_balances == TriState::True;
+}
+
+void
+xaccAccountSetIncludeSubAccountBalances (Account *acc, gboolean inc_sub)
+{
+ g_return_if_fail (GNC_IS_ACCOUNT(acc));
+
+ if (inc_sub != xaccAccountGetIncludeSubAccountBalances (acc))
+ {
+ GValue v = G_VALUE_INIT;
+ g_value_init (&v, G_TYPE_BOOLEAN);
+ g_value_set_boolean (&v, inc_sub);
+ std::vector<std::string> path {KEY_BALANCE_LIMIT,
+ KEY_BALANCE_INCLUDE_SUB_ACCTS};
+ xaccAccountBeginEdit (acc);
+ if (inc_sub)
+ qof_instance_set_path_kvp (QOF_INSTANCE(acc), &v, path);
+ else
+ qof_instance_set_path_kvp (QOF_INSTANCE(acc), nullptr, path);
+ GET_PRIVATE(acc)->include_sub_account_balances =
+ inc_sub ? TriState::True : TriState::False;
+ mark_account (acc);
+ xaccAccountCommitEdit (acc);
+ g_value_unset (&v);
+ }
+}
+
/********************************************************************\
\********************************************************************/
diff --git a/libgnucash/engine/Account.h b/libgnucash/engine/Account.h
index d84176d47..cc4fc6bd9 100644
--- a/libgnucash/engine/Account.h
+++ b/libgnucash/engine/Account.h
@@ -1233,6 +1233,22 @@ typedef enum
* @param account The account to clear the limit on
*/
void xaccAccountClearLowerBalanceLimit (Account *account);
+
+ /** Get whether to include balances of sub accounts.
+ *
+ * @param account The account to get setting on
+ *
+ * @return TRUE to include, default is FALSE
+ */
+ gboolean xaccAccountGetIncludeSubAccountBalances (const Account *account);
+
+ /** Set whether to include balances of sub accounts.
+ *
+ * @param account The account to set the setting on
+ *
+ * @param include Set to TRUE for including sub account balances
+ */
+ void xaccAccountSetIncludeSubAccountBalances (Account *account, gboolean include);
/** @} */
/** DOCUMENT ME! */
diff --git a/libgnucash/engine/AccountP.h b/libgnucash/engine/AccountP.h
index 68017ba9c..9de148482 100644
--- a/libgnucash/engine/AccountP.h
+++ b/libgnucash/engine/AccountP.h
@@ -125,7 +125,8 @@ typedef struct AccountPrivate
gboolean higher_balance_cached;
gnc_numeric lower_balance_limit;
gboolean lower_balance_cached;
-
+ TriState include_sub_account_balances;
+
gboolean balance_dirty; /* balances in splits incorrect */
GList *splits; /* list of split pointers */
commit 841b06940ea846c34653735b2d66ed7e19a4795e
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Tue Dec 13 11:43:25 2022 +0000
Use new tree view function to display icon in COA
diff --git a/gnucash/gnome-utils/gnc-tree-model-account.c b/gnucash/gnome-utils/gnc-tree-model-account.c
index 9a9cdb870..7f083c434 100644
--- a/gnucash/gnome-utils/gnc-tree-model-account.c
+++ b/gnucash/gnome-utils/gnc-tree-model-account.c
@@ -394,6 +394,7 @@ gnc_tree_model_account_get_column_type (GtkTreeModel *tree_model, int index)
case GNC_TREE_MODEL_ACCOUNT_COL_BALANCE:
case GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_REPORT:
case GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_PERIOD:
+ case GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_LIMIT:
case GNC_TREE_MODEL_ACCOUNT_COL_CLEARED:
case GNC_TREE_MODEL_ACCOUNT_COL_CLEARED_REPORT:
case GNC_TREE_MODEL_ACCOUNT_COL_RECONCILED:
@@ -830,6 +831,17 @@ gnc_tree_model_account_get_value (GtkTreeModel *tree_model,
g_free (string);
break;
+ case GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_LIMIT:
+ g_value_init (value, G_TYPE_STRING);
+ if (gnc_ui_account_is_higher_balance_limit_reached (account))
+ string = "go-top";
+ else if (gnc_ui_account_is_lower_balance_limit_reached (account))
+ string = "go-bottom";
+ else
+ string = "";
+ g_value_set_string (value, string);
+ break;
+
case GNC_TREE_MODEL_ACCOUNT_COL_CLEARED:
g_value_init (value, G_TYPE_STRING);
string = gnc_ui_account_get_print_balance (xaccAccountGetClearedBalanceInCurrency,
diff --git a/gnucash/gnome-utils/gnc-tree-model-account.h b/gnucash/gnome-utils/gnc-tree-model-account.h
index 177587305..5fcd42836 100644
--- a/gnucash/gnome-utils/gnc-tree-model-account.h
+++ b/gnucash/gnome-utils/gnc-tree-model-account.h
@@ -66,6 +66,7 @@ typedef enum
GNC_TREE_MODEL_ACCOUNT_COL_BALANCE,
GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_REPORT,
GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_PERIOD,
+ GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_LIMIT,
GNC_TREE_MODEL_ACCOUNT_COL_CLEARED,
GNC_TREE_MODEL_ACCOUNT_COL_CLEARED_REPORT,
GNC_TREE_MODEL_ACCOUNT_COL_RECONCILED,
diff --git a/gnucash/gnome-utils/gnc-tree-view-account.c b/gnucash/gnome-utils/gnc-tree-view-account.c
index b5b106f78..dc39c034f 100644
--- a/gnucash/gnome-utils/gnc-tree-view-account.c
+++ b/gnucash/gnome-utils/gnc-tree-view-account.c
@@ -763,7 +763,7 @@ gnc_tree_view_account_new_with_root (Account *root, gboolean show_root)
GtkTreePath *virtual_root_path = NULL;
const gchar *sample_type, *sample_commodity;
GncTreeViewAccountPrivate *priv;
- GtkTreeViewColumn *tax_info_column, *acc_color_column;
+ GtkTreeViewColumn *tax_info_column, *acc_color_column, *acc_balance_limit_column;
GtkCellRenderer *renderer;
GList *col_list = NULL, *node = NULL;
@@ -957,6 +957,22 @@ gnc_tree_view_account_new_with_root (Account *root, gboolean show_root)
/* Also add the full title to the column header as a tooltip */
gtk_widget_set_tooltip_text (gtk_tree_view_column_get_button (acc_color_column), _("Account Color"));
+ acc_balance_limit_column
+ = gnc_tree_view_add_pix_column (view,
+ C_("Column header for 'Balance Limit'", "L"),
+ "account-balance-limit",
+ "xx",
+ GNC_TREE_MODEL_ACCOUNT_COL_BALANCE_LIMIT,
+ GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+ NULL);
+
+ /* Add the full title to the object for menu creation */
+ g_object_set_data_full(G_OBJECT(acc_balance_limit_column), REAL_TITLE,
+ g_strdup(_("Balance Limit")), g_free);
+
+ /* Also add the full title to the column header as a tooltip */
+ gtk_widget_set_tooltip_text (gtk_tree_view_column_get_button (acc_balance_limit_column), _("Balance Limit"));
+
priv->notes_column
= gnc_tree_view_add_text_view_column(view, _("Notes"), "notes", NULL,
"Sample account notes.",
commit 60ab654d2ba0021407a92c5fb877251278da910d
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Tue Dec 13 11:42:40 2022 +0000
Add account balance test functions to gnc-ui-balance
diff --git a/libgnucash/app-utils/gnc-ui-balances.c b/libgnucash/app-utils/gnc-ui-balances.c
index 9227aefb2..222ba658a 100644
--- a/libgnucash/app-utils/gnc-ui-balances.c
+++ b/libgnucash/app-utils/gnc-ui-balances.c
@@ -250,6 +250,70 @@ gnc_ui_account_get_reconciled_balance_as_of_date (Account *account,
xaccAccountGetReconciledBalanceAsOfDate);
}
+static gint
+account_balance_limit_reached (const Account *account, gnc_numeric balance_limit)
+{
+ // we use today's date because account may have future dated splits
+ gnc_numeric balance = xaccAccountGetBalanceAsOfDate ((Account*)account,
+ gnc_time64_get_day_end (gnc_time (NULL)));
+
+ if (gnc_numeric_zero_p (balance))
+ return 0;
+
+ if (gnc_reverse_balance (account))
+ balance_limit = gnc_numeric_neg (balance_limit);
+
+ // Returns 1 if a>b, -1 if b>a, 0 if a == b
+ return gnc_numeric_compare (balance, balance_limit);
+}
+
+gboolean
+gnc_ui_account_is_higher_balance_limit_reached (const Account *account)
+{
+ gnc_numeric balance_limit;
+ gboolean limit_valid = FALSE;
+ gboolean retval = FALSE;
+ gint compare_result;
+
+ g_return_val_if_fail (GNC_IS_ACCOUNT(account), FALSE);
+
+ if (gnc_reverse_balance (account))
+ limit_valid = xaccAccountGetLowerBalanceLimit (account, &balance_limit);
+ else
+ limit_valid = xaccAccountGetHigherBalanceLimit (account, &balance_limit);
+
+ if (!limit_valid)
+ return retval;
+
+ if (account_balance_limit_reached (account, balance_limit) == 1)
+ retval = TRUE;
+
+ return retval;
+}
+
+gboolean
+gnc_ui_account_is_lower_balance_limit_reached (const Account *account)
+{
+ gnc_numeric balance_limit;
+ gboolean limit_valid = FALSE;
+ gboolean retval = FALSE;
+ gint compare_result;
+
+ g_return_val_if_fail (GNC_IS_ACCOUNT(account), FALSE);
+
+ if (gnc_reverse_balance (account))
+ limit_valid = xaccAccountGetHigherBalanceLimit (account, &balance_limit);
+ else
+ limit_valid = xaccAccountGetLowerBalanceLimit (account, &balance_limit);
+
+ if (!limit_valid)
+ return retval;
+
+ if (account_balance_limit_reached (account, balance_limit) == -1)
+ retval = TRUE;
+
+ return retval;
+}
/********************************************************************
* Balance calculations related to owners
diff --git a/libgnucash/app-utils/gnc-ui-balances.h b/libgnucash/app-utils/gnc-ui-balances.h
index 67d5f05e0..2cf0506de 100644
--- a/libgnucash/app-utils/gnc-ui-balances.h
+++ b/libgnucash/app-utils/gnc-ui-balances.h
@@ -154,4 +154,24 @@ gchar * gnc_ui_owner_get_print_report_balance (GncOwner *owner,
*/
GList * gnc_account_get_autoclear_splits (Account *account, gnc_numeric toclear_value,
gchar **errmsg);
+
+/** Test the account balance as of today for it passing the
+ * higher limit if set.
+ *
+ * @param account A pointer to the account.
+ *
+ * @return TRUE if account balance has passed limit.
+ */
+gboolean gnc_ui_account_is_higher_balance_limit_reached (const Account *account);
+
+/** Test the account balance as of today for it passing the
+ * lower limit if set.
+ *
+ * @param account A pointer to the account.
+ *
+ * @return TRUE if account balance has passed limit.
+ */
+gboolean gnc_ui_account_is_lower_balance_limit_reached (const Account *account);
+
+
#endif /* GNC_UI_BALANCES_H_ */
commit 5108c52ea40a0cf92bac4304405756db140e71ba
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Tue Dec 13 11:40:18 2022 +0000
Add new function to gnc-tree-view to display icon column
diff --git a/gnucash/gnome-utils/gnc-tree-view.c b/gnucash/gnome-utils/gnc-tree-view.c
index 201d770e2..994dbdf34 100644
--- a/gnucash/gnome-utils/gnc-tree-view.c
+++ b/gnucash/gnome-utils/gnc-tree-view.c
@@ -1957,6 +1957,63 @@ gnc_tree_view_add_text_view_column (GncTreeView *view,
column_sort_fn);
}
+/** This function adds a new pixbuf view column to a GncTreeView base view.
+ * It takes all the parameters necessary to hook a GtkTreeModel
+ * column to a GtkTreeViewColumn. If the tree has a state section
+ * associated with it, this function also wires up the column so that
+ * its visibility and width are remembered.
+ *
+ * Parameters are defined in gnc-tree-view.h
+ */
+GtkTreeViewColumn *
+gnc_tree_view_add_pix_column (GncTreeView *view,
+ const gchar *column_title,
+ const gchar *pref_name,
+ const gchar *sizing_text,
+ gint model_data_column,
+ gint model_visibility_column,
+ GtkTreeIterCompareFunc column_sort_fn)
+{
+ GtkTreeViewColumn *column;
+ PangoLayout* layout;
+ int default_width, title_width;
+ GtkCellRenderer *renderer;
+
+ g_return_val_if_fail (GNC_IS_TREE_VIEW(view), NULL);
+
+ renderer = gtk_cell_renderer_pixbuf_new ();
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, column_title);
+
+ /* Set up a text renderer and attributes */
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+
+ /* Set renderer attributes controlled by the model */
+ if (model_data_column != GNC_TREE_VIEW_COLUMN_DATA_NONE)
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "icon-name", model_data_column);
+ if (model_visibility_column != GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS)
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "visible", model_visibility_column);
+
+ /* Default size is the larger of the column title and the sizing text */
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET(view), column_title);
+ pango_layout_get_pixel_size (layout, &title_width, NULL);
+ g_object_unref (layout);
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET(view), sizing_text);
+ pango_layout_get_pixel_size (layout, &default_width, NULL);
+ g_object_unref (layout);
+ default_width = MAX(default_width, title_width);
+ if (default_width)
+ default_width += 10; /* padding on either side */
+ gnc_tree_view_column_properties (view, column, pref_name, model_data_column,
+ default_width, TRUE, column_sort_fn);
+
+ gnc_tree_view_append_column (view, column);
+ return column;
+}
+
/** This function adds a new date column to a GncTreeView base view.
* It takes all the parameters necessary to hook a GtkTreeModel
diff --git a/gnucash/gnome-utils/gnc-tree-view.h b/gnucash/gnome-utils/gnc-tree-view.h
index ee2d1eaa3..9c8928064 100644
--- a/gnucash/gnome-utils/gnc-tree-view.h
+++ b/gnucash/gnome-utils/gnc-tree-view.h
@@ -246,6 +246,47 @@ gnc_tree_view_add_text_view_column (GncTreeView *view,
gint model_visibility_column,
GtkTreeIterCompareFunc column_sort_fn);
+/** This function adds a pixbuf view column to a GncTreeView base view.
+ * It takes all the parameters necessary to hook a GtkTreeModel
+ * column to a GtkTreeViewColumn.
+ *
+ * @param view A pointer to a generic GncTreeView.
+ *
+ * @param column_title The title for this column.
+ *
+ * @param pref_name The internal name of this column. This name is
+ * used in several functions to look up the column, and it is also
+ * used when saving/restoring the view's state.
+ *
+ * @param sizing_text A string used to compute the default width of
+ * the column. This text is never displayed.
+ *
+ * @param model_data_column The index of the GtkTreeModel data column
+ * used to determine the data that will be displayed in this column
+ * for each row in the view. Use GNC_TREE_VIEW_COLUMN_DATA_NONE if
+ * you plan on using a non-model data source for this column. This
+ * index is connected to the "icon-name" attribute of the cell renderer.
+ *
+ * @param model_visibility_column The index of the GtkTreeModel data
+ * column used to determine whether or not a checkbox for each row
+ * will be displayed at all. Use GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS
+ * if the checkbox should be displayed in all rows.
+ *
+ * @param column_sort_fn The function that GtkTreeModelSort
+ * will call to compare two rows to determine their displayed
+ * order.
+ *
+ * @return The newly created GtkTreeViewColumn.
+ */
+GtkTreeViewColumn *
+gnc_tree_view_add_pix_column (GncTreeView *view,
+ const gchar *column_title,
+ const gchar *pref_name,
+ const gchar *sizing_text,
+ gint model_data_column,
+ gint model_visibility_column,
+ GtkTreeIterCompareFunc column_sort_fn);
+
/** This function adds a new combobox column to a GncTreeView base
* view. The parameters it takes in common with
* gnc_tree_view_add_text_column() behave the same as there. In
commit fb84cf7d1668c0574fc9ec82f31269fb2b3984d6
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Tue Dec 13 11:39:47 2022 +0000
Add entry to dialog-account to set account balance limits
diff --git a/gnucash/gnome-utils/dialog-account.c b/gnucash/gnome-utils/dialog-account.c
index 63ab3808a..be426f1b9 100644
--- a/gnucash/gnome-utils/dialog-account.c
+++ b/gnucash/gnome-utils/dialog-account.c
@@ -106,6 +106,13 @@ typedef struct _AccountWindow
GtkTreeView *parent_tree;
GtkWidget *parent_scroll;
+ GtkWidget *more_properties_page;
+
+ GtkWidget *balance_grid;
+ GtkWidget *higher_balance_limit_edit;
+ GtkWidget *lower_balance_limit_edit;
+ gboolean balance_is_reversed;
+
GtkWidget *opening_balance_button;
GtkWidget *opening_balance_edit;
GtkWidget *opening_balance_date_edit;
@@ -250,6 +257,8 @@ gnc_account_to_ui (AccountWindow *aw)
GdkRGBA color;
gboolean flag, nonstd_scu;
gint index;
+ gnc_numeric balance_limit;
+ gboolean balance_limit_valid;
ENTER("%p", aw);
account = aw_get_account (aw);
@@ -325,6 +334,36 @@ gnc_account_to_ui (AccountWindow *aw)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(aw->hidden_button),
flag);
+ aw->balance_is_reversed = gnc_reverse_balance (account);
+
+ balance_limit_valid = xaccAccountGetHigherBalanceLimit (account, &balance_limit);
+ if (balance_limit_valid)
+ {
+ if (aw->balance_is_reversed)
+ {
+ balance_limit = gnc_numeric_neg (balance_limit);
+ gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(aw->lower_balance_limit_edit),
+ balance_limit);
+ }
+ else
+ gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(aw->higher_balance_limit_edit),
+ balance_limit);
+ }
+
+ balance_limit_valid = xaccAccountGetLowerBalanceLimit (account, &balance_limit);
+ if (balance_limit_valid)
+ {
+ if (aw->balance_is_reversed)
+ {
+ balance_limit = gnc_numeric_neg (balance_limit);
+ gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(aw->higher_balance_limit_edit),
+ balance_limit);
+ }
+ else
+ gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(aw->lower_balance_limit_edit),
+ balance_limit);
+ }
+
set_auto_interest_box (aw);
LEAVE(" ");
}
@@ -393,6 +432,8 @@ gnc_ui_to_account (AccountWindow *aw)
GdkRGBA color;
gboolean flag;
gnc_numeric balance;
+ gnc_numeric balance_limit;
+ gint balance_limit_valid;
gboolean use_equity, nonstd;
time64 date;
gint index, old_scu, new_scu;
@@ -505,6 +546,50 @@ gnc_ui_to_account (AccountWindow *aw)
if (parent_account != gnc_account_get_parent (account))
gnc_account_append_child (parent_account, account);
+ balance_limit_valid = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT(aw->higher_balance_limit_edit),
+ &balance_limit, TRUE, NULL);
+
+ if (balance_limit_valid == 0)
+ {
+ if (aw->balance_is_reversed)
+ {
+ balance_limit = gnc_numeric_neg (balance_limit);
+ xaccAccountSetLowerBalanceLimit (account, balance_limit);
+ }
+ else
+ xaccAccountSetHigherBalanceLimit (account, balance_limit);
+ }
+
+ if (balance_limit_valid == -1)
+ {
+ if (aw->balance_is_reversed)
+ xaccAccountClearLowerBalanceLimit (account);
+ else
+ xaccAccountClearHigherBalanceLimit (account);
+ }
+
+ balance_limit_valid = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT(aw->lower_balance_limit_edit),
+ &balance_limit, TRUE, NULL);
+
+ if (balance_limit_valid == 0)
+ {
+ if (aw->balance_is_reversed)
+ {
+ balance_limit = gnc_numeric_neg (balance_limit);
+ xaccAccountSetHigherBalanceLimit (account, balance_limit);
+ }
+ else
+ xaccAccountSetLowerBalanceLimit (account, balance_limit);
+ }
+
+ if (balance_limit_valid == -1)
+ {
+ if (aw->balance_is_reversed)
+ xaccAccountClearHigherBalanceLimit (account);
+ else
+ xaccAccountClearLowerBalanceLimit (account);
+ }
+
xaccAccountCommitEdit (account);
balance = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT(aw->opening_balance_edit));
@@ -811,6 +896,10 @@ gnc_common_ok (AccountWindow *aw)
gnc_commodity * commodity;
gchar *fullname, *fullname_parent;
const gchar *name, *separator;
+ gboolean higher_limit_valid;
+ gnc_numeric higher_balance_limit;
+ gboolean lower_limit_valid;
+ gnc_numeric lower_balance_limit;
ENTER("aw %p", aw);
root = gnc_book_get_root_account (aw->book);
@@ -892,6 +981,34 @@ gnc_common_ok (AccountWindow *aw)
return FALSE;
}
+ /* check for higher balance limit greater than lower */
+ higher_limit_valid = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT(aw->higher_balance_limit_edit),
+ &higher_balance_limit, TRUE, NULL);
+
+ lower_limit_valid = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT(aw->lower_balance_limit_edit),
+ &lower_balance_limit, TRUE, NULL);
+
+ if ((lower_limit_valid == 0) && (higher_limit_valid == 0))
+ {
+ gint compare = gnc_numeric_compare (higher_balance_limit,
+ lower_balance_limit);
+
+ if ((compare == 0) && (!gnc_numeric_zero_p (higher_balance_limit)))
+ {
+ const char *message = _("Balance limits must be different unless they are both zero.");
+ gnc_error_dialog (GTK_WINDOW(aw->dialog), "%s", message);
+ LEAVE("invalid balance limit, both the same but not zero");
+ return FALSE;
+ }
+ else if (compare == -1)
+ {
+ const char *message = _("The lower balance limit must be less than the higher limit.");
+ gnc_error_dialog (GTK_WINDOW(aw->dialog), "%s", message);
+ LEAVE("invalid balance limit, lower limit not less than upper");
+ return FALSE;
+ }
+ }
+
LEAVE("passed");
return TRUE;
}
@@ -1483,6 +1600,27 @@ gnc_account_window_create (GtkWindow *parent, AccountWindow *aw)
g_signal_connect (G_OBJECT(selection), "changed",
G_CALLBACK(gnc_account_parent_changed_cb), aw);
+ aw->balance_grid = GTK_WIDGET(gtk_builder_get_object (builder, "balance_grid"));
+
+ box = GTK_WIDGET(gtk_builder_get_object (builder, "higher_balance_limit_hbox"));
+ aw->higher_balance_limit_edit = gnc_amount_edit_new ();
+ gtk_box_pack_start (GTK_BOX(box), aw->higher_balance_limit_edit, TRUE, TRUE, 0);
+ gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT(aw->higher_balance_limit_edit), TRUE);
+ gnc_amount_edit_set_validate_on_change (GNC_AMOUNT_EDIT(aw->higher_balance_limit_edit), TRUE);
+ gnc_amount_edit_show_warning_symbol (GNC_AMOUNT_EDIT(aw->higher_balance_limit_edit), TRUE);
+ gtk_widget_show (aw->higher_balance_limit_edit);
+
+ box = GTK_WIDGET(gtk_builder_get_object (builder, "lower_balance_limit_hbox"));
+ aw->lower_balance_limit_edit = gnc_amount_edit_new ();
+ gtk_box_pack_start (GTK_BOX(box), aw->lower_balance_limit_edit, TRUE, TRUE, 0);
+ gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT(aw->lower_balance_limit_edit), TRUE);
+ gnc_amount_edit_set_validate_on_change (GNC_AMOUNT_EDIT(aw->lower_balance_limit_edit), TRUE);
+ gnc_amount_edit_show_warning_symbol (GNC_AMOUNT_EDIT(aw->lower_balance_limit_edit), TRUE);
+ gtk_widget_show (aw->lower_balance_limit_edit);
+
+ aw->more_properties_page =
+ gtk_notebook_get_nth_page (GTK_NOTEBOOK(aw->notebook), 1);
+
aw->opening_balance_button = GTK_WIDGET(gtk_builder_get_object (builder, "opening_balance_button"));
aw->tax_related_button = GTK_WIDGET(gtk_builder_get_object (builder, "tax_related_button"));
aw->placeholder_button = GTK_WIDGET(gtk_builder_get_object (builder, "placeholder_button"));
@@ -1510,7 +1648,7 @@ gnc_account_window_create (GtkWindow *parent, AccountWindow *aw)
gtk_widget_show (date_edit);
aw->opening_balance_page =
- gtk_notebook_get_nth_page (GTK_NOTEBOOK(aw->notebook), 1);
+ gtk_notebook_get_nth_page (GTK_NOTEBOOK(aw->notebook), 2);
aw->opening_equity_radio = GTK_WIDGET(gtk_builder_get_object (builder,
"opening_equity_radio"));
@@ -1965,6 +2103,14 @@ gnc_ui_edit_account_window (GtkWindow *parent, Account *account)
if (xaccAccountGetSplitList (account) != NULL)
gtk_widget_hide (aw->opening_balance_page);
+ // Note: we are hiding the notebook page here, when other items
+ // are added this will need adjusting.
+ if (gnc_account_n_children (account) > 0)
+ {
+ gtk_widget_hide (GTK_WIDGET(aw->balance_grid));
+ gtk_widget_hide (GTK_WIDGET(aw->more_properties_page));
+ }
+
parent_acct = gnc_account_get_parent (account);
if (parent_acct == NULL)
parent_acct = account; // must be at the root
diff --git a/gnucash/gtkbuilder/dialog-account.glade b/gnucash/gtkbuilder/dialog-account.glade
index 3447f545e..e81dc5c99 100644
--- a/gnucash/gtkbuilder/dialog-account.glade
+++ b/gnucash/gtkbuilder/dialog-account.glade
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.38.2 -->
+<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.22"/>
<object class="GtkDialog" id="account_cascade_dialog">
@@ -1682,7 +1682,138 @@
</packing>
</child>
<child>
- <object class="GtkBox" id="vbox302">
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border-width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">18</property>
+ <child>
+ <!-- n-columns=2 n-rows=3 -->
+ <object class="GtkGrid" id="balance_grid">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row-spacing">3</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="higher_balance_label">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">_Higher Balance Limit</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">higher_balance_limit_hbox</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="higher_balance_limit_hbox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="tooltip-text" translatable="yes">If a value is present, an indication can be shown in the chart of accounts when today's balance is more than this value.
+
+i.e.
+Today's balance of -90 will show icon if limit is set to -100
+Today's balance of 100 will show icon if limit is set to 90
+
+Clear the entry to have no warning.</property>
+ <property name="hexpand">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="lower_balance_limit_hbox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="tooltip-text" translatable="yes">If a value is present, an indication can be shown in the chart of accounts when today's balance is less than this value.
+
+i.e.
+Today's balance of -100 will show icon if limit is set to -90
+Today's balance of 90 will show icon if limit is set to 100
+
+Clear the entry to have no warning.</property>
+ <property name="hexpand">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="lower_balance_label">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">_Lower Balance Limit</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Balance Limit</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <style>
+ <class name="gnc-class-account"/>
+ </style>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes">More Properties</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab-fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="vbox1">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="border-width">6</property>
@@ -1857,7 +1988,7 @@
</style>
</object>
<packing>
- <property name="position">1</property>
+ <property name="position">2</property>
</packing>
</child>
<child type="tab">
@@ -1868,7 +1999,7 @@
<property name="justify">center</property>
</object>
<packing>
- <property name="position">1</property>
+ <property name="position">2</property>
<property name="tab-fill">False</property>
</packing>
</child>
commit 518ecfe04146ed4b60a1463d520bcd2bc20dc567
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Fri Dec 9 10:10:59 2022 +0000
Add some functions that would allow adding a balance limit to accounts
diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp
index d00e1aa52..f6863a0ce 100644
--- a/libgnucash/engine/Account.cpp
+++ b/libgnucash/engine/Account.cpp
@@ -73,6 +73,10 @@ static const std::string AB_ACCOUNT_UID("account-uid");
static const std::string AB_BANK_CODE("bank-code");
static const std::string AB_TRANS_RETRIEVAL("trans-retrieval");
+static const std::string KEY_BALANCE_LIMIT("balance-limit");
+static const std::string KEY_BALANCE_HIGHER_LIMIT_VALUE("higher-value");
+static const std::string KEY_BALANCE_LOWER_LIMIT_VALUE("lower-value");
+
static gnc_numeric GetBalanceAsOfDate (Account *acc, time64 date, gboolean ignclosing);
using FinalProbabilityVec=std::vector<std::pair<std::string, int32_t>>;
@@ -328,6 +332,11 @@ gnc_account_init(Account* acc)
priv->starting_reconciled_balance = gnc_numeric_zero();
priv->balance_dirty = FALSE;
+ priv->higher_balance_limit = gnc_numeric_create (1,0);
+ priv->higher_balance_cached = false;
+ priv->lower_balance_limit = gnc_numeric_create (1,0);
+ priv->lower_balance_cached = false;
+
priv->last_num = (char*) is_unset;
priv->tax_us_code = (char*) is_unset;
priv->tax_us_pns = (char*) is_unset;
@@ -4930,6 +4939,211 @@ xaccAccountSetLastNum (Account *acc, const char *num)
set_kvp_string_tag (acc, "last-num", priv->last_num);
}
+
+/********************************************************************\
+\********************************************************************/
+
+gboolean
+xaccAccountGetHigherBalanceLimit (const Account *acc,
+ gnc_numeric *balance)
+{
+ g_return_val_if_fail (GNC_IS_ACCOUNT(acc), false);
+
+ if (GET_PRIVATE(acc)->higher_balance_cached)
+ {
+ *balance = GET_PRIVATE(acc)->higher_balance_limit;
+
+ if (gnc_numeric_check (*balance) == 0)
+ return true;
+ else
+ return false;
+ }
+ else
+ {
+ gnc_numeric bal = gnc_numeric_create (1,0);
+ GValue v = G_VALUE_INIT;
+ gboolean retval = false;
+
+ qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v, {KEY_BALANCE_LIMIT,
+ KEY_BALANCE_HIGHER_LIMIT_VALUE});
+ if (G_VALUE_HOLDS_BOXED(&v))
+ {
+ bal = *(gnc_numeric*)g_value_get_boxed (&v);
+ if (bal.denom)
+ {
+ if (balance)
+ *balance = bal;
+ retval = true;
+ }
+ }
+ g_value_unset (&v);
+
+ GET_PRIVATE(acc)->higher_balance_limit = bal;
+ GET_PRIVATE(acc)->higher_balance_cached = true;
+ return retval;
+ }
+}
+
+gboolean
+xaccAccountGetLowerBalanceLimit (const Account *acc,
+ gnc_numeric *balance)
+{
+ g_return_val_if_fail (GNC_IS_ACCOUNT(acc), false);
+
+ if (GET_PRIVATE(acc)->lower_balance_cached)
+ {
+ *balance = GET_PRIVATE(acc)->lower_balance_limit;
+
+ if (gnc_numeric_check (*balance) == 0)
+ return true;
+ else
+ return false;
+ }
+ else
+ {
+ gnc_numeric bal = gnc_numeric_create (1,0);
+ GValue v = G_VALUE_INIT;
+ gboolean retval = false;
+
+ qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v, {KEY_BALANCE_LIMIT,
+ KEY_BALANCE_LOWER_LIMIT_VALUE});
+ if (G_VALUE_HOLDS_BOXED(&v))
+ {
+ bal = *(gnc_numeric*)g_value_get_boxed (&v);
+ if (bal.denom)
+ {
+ if (balance)
+ *balance = bal;
+ retval = true;
+ }
+ }
+ g_value_unset (&v);
+
+ GET_PRIVATE(acc)->lower_balance_limit = bal;
+ GET_PRIVATE(acc)->lower_balance_cached = true;
+ return retval;
+ }
+}
+
+
+static void
+set_balance_limits (Account *acc, gnc_numeric balance, gboolean higher)
+{
+ gnc_numeric balance_limit;
+ gboolean balance_limit_valid;
+ std::vector<std::string> path {KEY_BALANCE_LIMIT};
+
+ if (higher)
+ {
+ path.push_back (KEY_BALANCE_HIGHER_LIMIT_VALUE);
+ balance_limit_valid = xaccAccountGetHigherBalanceLimit (acc, &balance_limit);
+ }
+ else
+ {
+ path.push_back (KEY_BALANCE_LOWER_LIMIT_VALUE);
+ balance_limit_valid = xaccAccountGetLowerBalanceLimit (acc, &balance_limit);
+ }
+
+ if (!balance_limit_valid || gnc_numeric_compare (balance, balance_limit) != 0)
+ {
+ GValue v = G_VALUE_INIT;
+ g_value_init (&v, GNC_TYPE_NUMERIC);
+ g_value_set_boxed (&v, &balance);
+ xaccAccountBeginEdit (acc);
+
+ qof_instance_set_path_kvp (QOF_INSTANCE(acc), &v, path);
+ if (higher)
+ {
+ GET_PRIVATE(acc)->higher_balance_limit.denom = balance.denom;
+ GET_PRIVATE(acc)->higher_balance_limit.num = balance.num;
+ GET_PRIVATE(acc)->higher_balance_cached = true;
+ }
+ else
+ {
+ GET_PRIVATE(acc)->lower_balance_limit.denom = balance.denom;
+ GET_PRIVATE(acc)->lower_balance_limit.num = balance.num;
+ GET_PRIVATE(acc)->lower_balance_cached = true;
+ }
+ mark_account (acc);
+ xaccAccountCommitEdit (acc);
+ g_value_unset (&v);
+ }
+}
+
+void
+xaccAccountSetHigherBalanceLimit (Account *acc, gnc_numeric balance)
+{
+ g_return_if_fail (GNC_IS_ACCOUNT(acc));
+
+ if (gnc_numeric_check (balance) != 0)
+ return;
+
+ set_balance_limits (acc, balance, true);
+}
+
+void
+xaccAccountSetLowerBalanceLimit (Account *acc, gnc_numeric balance)
+{
+ g_return_if_fail (GNC_IS_ACCOUNT(acc));
+
+ if (gnc_numeric_check (balance) != 0)
+ return;
+
+ set_balance_limits (acc, balance, false);
+}
+
+
+static void
+clear_balance_limits (Account *acc, gboolean higher)
+{
+ gnc_numeric balance_limit;
+ gboolean balance_limit_valid;
+ std::vector<std::string> path {KEY_BALANCE_LIMIT};
+
+ if (higher)
+ {
+ path.push_back (KEY_BALANCE_HIGHER_LIMIT_VALUE);
+ balance_limit_valid = xaccAccountGetHigherBalanceLimit (acc, &balance_limit);
+ }
+ else
+ {
+ path.push_back (KEY_BALANCE_LOWER_LIMIT_VALUE);
+ balance_limit_valid = xaccAccountGetLowerBalanceLimit (acc, &balance_limit);
+ }
+
+ if (balance_limit_valid)
+ {
+ xaccAccountBeginEdit (acc);
+ qof_instance_set_path_kvp (QOF_INSTANCE(acc), nullptr, path);
+ qof_instance_slot_path_delete_if_empty (QOF_INSTANCE(acc), {KEY_BALANCE_LIMIT});
+ if (higher)
+ GET_PRIVATE(acc)->higher_balance_cached = false;
+ else
+ GET_PRIVATE(acc)->lower_balance_cached = false;
+ mark_account (acc);
+ xaccAccountCommitEdit (acc);
+ }
+}
+
+void
+xaccAccountClearHigherBalanceLimit (Account *acc)
+{
+ g_return_if_fail (GNC_IS_ACCOUNT(acc));
+
+ clear_balance_limits (acc, true);
+}
+
+void
+xaccAccountClearLowerBalanceLimit (Account *acc)
+{
+ g_return_if_fail (GNC_IS_ACCOUNT(acc));
+
+ clear_balance_limits (acc, false);
+}
+
+/********************************************************************\
+\********************************************************************/
+
static Account *
GetOrMakeOrphanAccount (Account *root, gnc_commodity * currency)
{
diff --git a/libgnucash/engine/Account.h b/libgnucash/engine/Account.h
index 3fac9bdbb..d84176d47 100644
--- a/libgnucash/engine/Account.h
+++ b/libgnucash/engine/Account.h
@@ -1182,6 +1182,58 @@ typedef enum
void xaccAccountClearReconcilePostpone (Account *account);
/** @} */
+ /** @name Account Balance Limits
+ @{
+ */
+
+ /** Get the higher balance limit for the account.
+ *
+ * @param account The account whose higher limit is to be retrieved
+ *
+ * @param balance The placeholder to store the retrieved balance
+ *
+ * @return True if the limit is valid. */
+ gboolean xaccAccountGetHigherBalanceLimit (const Account *account,
+ gnc_numeric *balance);
+
+ /** Set the higher balance limit for the account.
+ *
+ * @param account The account whose higher limit is to be saved
+ *
+ * @param balance The balance to be saved
+ */
+ void xaccAccountSetHigherBalanceLimit (Account *account, gnc_numeric balance);
+
+ /** Clear the higher balance limit for the account.
+ *
+ * @param account The account to clear the limit on
+ */
+ void xaccAccountClearHigherBalanceLimit (Account *account);
+
+ /** Get the lower balance limit for the account.
+ *
+ * @param account The account whose lower limit is to be retrieved
+ *
+ * @param balance The placeholder to store the retrieved balance
+ *
+ * @return True if the limit is valid. */
+ gboolean xaccAccountGetLowerBalanceLimit (const Account *account,
+ gnc_numeric *balance);
+
+ /** Set the lower balance limit for the account.
+ *
+ * @param account The account whose lower limit is to be saved
+ *
+ * @param balance The balance to be saved
+ */
+ void xaccAccountSetLowerBalanceLimit (Account *account, gnc_numeric balance);
+
+ /** Clear the lower balance limit for the account.
+ *
+ * @param account The account to clear the limit on
+ */
+ void xaccAccountClearLowerBalanceLimit (Account *account);
+ /** @} */
/** DOCUMENT ME! */
typedef enum
diff --git a/libgnucash/engine/AccountP.h b/libgnucash/engine/AccountP.h
index 14faeb6c0..68017ba9c 100644
--- a/libgnucash/engine/AccountP.h
+++ b/libgnucash/engine/AccountP.h
@@ -121,6 +121,11 @@ typedef struct AccountPrivate
gnc_numeric cleared_balance;
gnc_numeric reconciled_balance;
+ gnc_numeric higher_balance_limit;
+ gboolean higher_balance_cached;
+ gnc_numeric lower_balance_limit;
+ gboolean lower_balance_cached;
+
gboolean balance_dirty; /* balances in splits incorrect */
GList *splits; /* list of split pointers */
Summary of changes:
gnucash/gnome-utils/dialog-account.c | 159 ++++++++++++++++-
gnucash/gnome-utils/gnc-tree-model-account.c | 7 +
gnucash/gnome-utils/gnc-tree-model-account.h | 1 +
gnucash/gnome-utils/gnc-tree-view-account.c | 18 +-
gnucash/gnome-utils/gnc-tree-view.c | 57 ++++++
gnucash/gnome-utils/gnc-tree-view.h | 41 +++++
gnucash/gtkbuilder/dialog-account.glade | 156 +++++++++++++++-
libgnucash/app-utils/gnc-ui-balances.c | 105 +++++++++++
libgnucash/app-utils/gnc-ui-balances.h | 32 ++++
libgnucash/engine/Account.cpp | 257 +++++++++++++++++++++++++++
libgnucash/engine/Account.h | 68 +++++++
libgnucash/engine/AccountP.h | 6 +
libgnucash/engine/test/utest-Account.cpp | 29 +++
13 files changed, 930 insertions(+), 6 deletions(-)
More information about the gnucash-changes
mailing list