mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Bug 603379 - Prevent changing some Account Options if it has transactions - followup
Relax the account type change restrictions again. In the new implementation account types can't be changed for an account with splits: - if the change woud force a commodity change (to/from normal accounts from/to stock related accounts) - for immutable accounts At the time of this commit the following account types are considered immutable: - Accounts Receivable - Accounts Payable - Trading accounts
This commit is contained in:
parent
4032d33b48
commit
c80dad742e
@ -4029,6 +4029,46 @@ xaccAccountGetTypeStr(GNCAccountType type)
|
|||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
|
|
||||||
|
guint32
|
||||||
|
xaccAccountTypesCompatibleWith (GNCAccountType type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ACCT_TYPE_BANK:
|
||||||
|
case ACCT_TYPE_CASH:
|
||||||
|
case ACCT_TYPE_ASSET:
|
||||||
|
case ACCT_TYPE_CREDIT:
|
||||||
|
case ACCT_TYPE_LIABILITY:
|
||||||
|
case ACCT_TYPE_INCOME:
|
||||||
|
case ACCT_TYPE_EXPENSE:
|
||||||
|
case ACCT_TYPE_EQUITY:
|
||||||
|
return
|
||||||
|
(1 << ACCT_TYPE_BANK) |
|
||||||
|
(1 << ACCT_TYPE_CASH) |
|
||||||
|
(1 << ACCT_TYPE_ASSET) |
|
||||||
|
(1 << ACCT_TYPE_CREDIT) |
|
||||||
|
(1 << ACCT_TYPE_LIABILITY) |
|
||||||
|
(1 << ACCT_TYPE_INCOME) |
|
||||||
|
(1 << ACCT_TYPE_EXPENSE) |
|
||||||
|
(1 << ACCT_TYPE_EQUITY);
|
||||||
|
case ACCT_TYPE_STOCK:
|
||||||
|
case ACCT_TYPE_MUTUAL:
|
||||||
|
case ACCT_TYPE_CURRENCY:
|
||||||
|
return
|
||||||
|
(1 << ACCT_TYPE_STOCK) |
|
||||||
|
(1 << ACCT_TYPE_MUTUAL) |
|
||||||
|
(1 << ACCT_TYPE_CURRENCY);
|
||||||
|
case ACCT_TYPE_RECEIVABLE:
|
||||||
|
return (1 << ACCT_TYPE_RECEIVABLE);
|
||||||
|
case ACCT_TYPE_PAYABLE:
|
||||||
|
return (1 << ACCT_TYPE_PAYABLE);
|
||||||
|
case ACCT_TYPE_TRADING:
|
||||||
|
return (1 << ACCT_TYPE_TRADING);
|
||||||
|
default:
|
||||||
|
PERR("bad account type: %d", type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
guint32
|
guint32
|
||||||
xaccParentAccountTypesCompatibleWith (GNCAccountType type)
|
xaccParentAccountTypesCompatibleWith (GNCAccountType type)
|
||||||
{
|
{
|
||||||
|
@ -926,6 +926,11 @@ GNCAccountType xaccAccountStringToEnum (const char* str);
|
|||||||
* to the local language. */
|
* to the local language. */
|
||||||
const char * xaccAccountGetTypeStr (GNCAccountType type);
|
const char * xaccAccountGetTypeStr (GNCAccountType type);
|
||||||
|
|
||||||
|
/** Return the bitmask of account types compatible with a given type.
|
||||||
|
* That is, you could switch to any of the account types in the compatible
|
||||||
|
* list without unwanted side-effects. */
|
||||||
|
guint32 xaccAccountTypesCompatibleWith (GNCAccountType type);
|
||||||
|
|
||||||
/** Return the bitmask of parent account types compatible with a given type. */
|
/** Return the bitmask of parent account types compatible with a given type. */
|
||||||
guint32 xaccParentAccountTypesCompatibleWith (GNCAccountType type);
|
guint32 xaccParentAccountTypesCompatibleWith (GNCAccountType type);
|
||||||
|
|
||||||
|
@ -2189,6 +2189,7 @@ test_xaccAccountType_Stuff (void)
|
|||||||
}
|
}
|
||||||
/* xaccParentAccountTypesCompatibleWith
|
/* xaccParentAccountTypesCompatibleWith
|
||||||
* xaccAccountTypesCompatible
|
* xaccAccountTypesCompatible
|
||||||
|
* xaccAccountTypesCompatibleWith
|
||||||
guint32
|
guint32
|
||||||
xaccParentAccountTypesCompatibleWith (GNCAccountType type)// C: 5 in 3 */
|
xaccParentAccountTypesCompatibleWith (GNCAccountType type)// C: 5 in 3 */
|
||||||
static void
|
static void
|
||||||
@ -2210,6 +2211,20 @@ test_xaccAccountType_Compatibility (void)
|
|||||||
(1 << ACCT_TYPE_ROOT));
|
(1 << ACCT_TYPE_ROOT));
|
||||||
guint32 equity_compat = ((1 << ACCT_TYPE_EQUITY) | (1 << ACCT_TYPE_ROOT));
|
guint32 equity_compat = ((1 << ACCT_TYPE_EQUITY) | (1 << ACCT_TYPE_ROOT));
|
||||||
guint32 trading_compat = ((1 << ACCT_TYPE_TRADING) | (1 << ACCT_TYPE_ROOT));
|
guint32 trading_compat = ((1 << ACCT_TYPE_TRADING) | (1 << ACCT_TYPE_ROOT));
|
||||||
|
guint32 currency_compat = ((1 << ACCT_TYPE_BANK) |
|
||||||
|
(1 << ACCT_TYPE_CASH) |
|
||||||
|
(1 << ACCT_TYPE_ASSET) |
|
||||||
|
(1 << ACCT_TYPE_CREDIT) |
|
||||||
|
(1 << ACCT_TYPE_LIABILITY) |
|
||||||
|
(1 << ACCT_TYPE_INCOME) |
|
||||||
|
(1 << ACCT_TYPE_EXPENSE) |
|
||||||
|
(1 << ACCT_TYPE_EQUITY));
|
||||||
|
guint32 stock_compat = ((1 << ACCT_TYPE_STOCK) |
|
||||||
|
(1 << ACCT_TYPE_MUTUAL) |
|
||||||
|
(1 << ACCT_TYPE_CURRENCY));
|
||||||
|
guint32 immutable_ar_compat = (1 << ACCT_TYPE_RECEIVABLE);
|
||||||
|
guint32 immutable_ap_compat = (1 << ACCT_TYPE_PAYABLE);
|
||||||
|
guint32 immutable_trading_compat = (1 << ACCT_TYPE_TRADING);
|
||||||
guint32 compat;
|
guint32 compat;
|
||||||
GNCAccountType type;
|
GNCAccountType type;
|
||||||
gchar *msg1 = g_strdup_printf ("[xaccParentAccountTypesCompatibleWith()] bad account type: %d", ACCT_TYPE_ROOT);
|
gchar *msg1 = g_strdup_printf ("[xaccParentAccountTypesCompatibleWith()] bad account type: %d", ACCT_TYPE_ROOT);
|
||||||
@ -2252,6 +2267,19 @@ test_xaccAccountType_Compatibility (void)
|
|||||||
g_assert (xaccAccountTypesCompatible (type, child));
|
g_assert (xaccAccountTypesCompatible (type, child));
|
||||||
else
|
else
|
||||||
g_assert (!xaccAccountTypesCompatible (type, child));
|
g_assert (!xaccAccountTypesCompatible (type, child));
|
||||||
|
|
||||||
|
compat = xaccAccountTypesCompatibleWith (type);
|
||||||
|
if (type <= ACCT_TYPE_LIABILITY ||
|
||||||
|
(type >= ACCT_TYPE_INCOME && type <= ACCT_TYPE_EQUITY))
|
||||||
|
g_assert_cmpint (compat, == , currency_compat);
|
||||||
|
else if (type >= ACCT_TYPE_STOCK && type <= ACCT_TYPE_CURRENCY)
|
||||||
|
g_assert_cmpint (compat, == , stock_compat);
|
||||||
|
else if (type == ACCT_TYPE_RECEIVABLE)
|
||||||
|
g_assert_cmpint (compat, == , immutable_ar_compat);
|
||||||
|
else if (type == ACCT_TYPE_PAYABLE)
|
||||||
|
g_assert_cmpint (compat, == , immutable_ap_compat);
|
||||||
|
else if (type == ACCT_TYPE_TRADING)
|
||||||
|
g_assert_cmpint (compat, == , immutable_trading_compat);
|
||||||
}
|
}
|
||||||
|
|
||||||
loghandler = g_log_set_handler (logdomain, loglevel,
|
loghandler = g_log_set_handler (logdomain, loglevel,
|
||||||
|
@ -1120,17 +1120,18 @@ gnc_account_type_changed_cb (GtkTreeSelection *selection, gpointer data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gnc_account_type_view_create (AccountWindow *aw)
|
gnc_account_type_view_create (AccountWindow *aw, guint32 compat_types)
|
||||||
{
|
{
|
||||||
GtkTreeModel *model;
|
GtkTreeModel *model;
|
||||||
GtkTreeSelection *selection;
|
GtkTreeSelection *selection;
|
||||||
GtkCellRenderer *renderer;
|
GtkCellRenderer *renderer;
|
||||||
GtkTreeView *view;
|
GtkTreeView *view;
|
||||||
|
|
||||||
|
aw->valid_types &= compat_types;
|
||||||
if (aw->valid_types == 0)
|
if (aw->valid_types == 0)
|
||||||
{
|
{
|
||||||
/* no type restrictions, choose aw->type */
|
/* no type restrictions, choose aw->type */
|
||||||
aw->valid_types = xaccAccountTypesValid () | (1 << aw->type);
|
aw->valid_types = compat_types | (1 << aw->type);
|
||||||
aw->preferred_account_type = aw->type;
|
aw->preferred_account_type = aw->type;
|
||||||
}
|
}
|
||||||
else if ((aw->valid_types & (1 << aw->type)) != 0)
|
else if ((aw->valid_types & (1 << aw->type)) != 0)
|
||||||
@ -1309,6 +1310,7 @@ gnc_account_window_create(AccountWindow *aw)
|
|||||||
GtkBuilder *builder;
|
GtkBuilder *builder;
|
||||||
GtkTreeSelection *selection;
|
GtkTreeSelection *selection;
|
||||||
const gchar *tt = _("This Account contains Transactions.\nChanging this option is not possible.");
|
const gchar *tt = _("This Account contains Transactions.\nChanging this option is not possible.");
|
||||||
|
guint32 compat_types = xaccAccountTypesValid ();
|
||||||
|
|
||||||
ENTER("aw %p, modal %d", aw, aw->modal);
|
ENTER("aw %p, modal %d", aw, aw->modal);
|
||||||
builder = gtk_builder_new();
|
builder = gtk_builder_new();
|
||||||
@ -1413,23 +1415,23 @@ gnc_account_window_create(AccountWindow *aw)
|
|||||||
|
|
||||||
/* This goes at the end so the select callback has good data. */
|
/* This goes at the end so the select callback has good data. */
|
||||||
aw->type_view = GTK_WIDGET(gtk_builder_get_object (builder, "type_view"));
|
aw->type_view = GTK_WIDGET(gtk_builder_get_object (builder, "type_view"));
|
||||||
gnc_account_type_view_create (aw);
|
|
||||||
|
|
||||||
// If the account has transactions, prevent changes by displaying a label and tooltip
|
// If the account has transactions, reduce the available account types
|
||||||
|
// to change the current account type to based on the following
|
||||||
|
// restrictions:
|
||||||
|
// - the new account type should not force a change of commodity
|
||||||
|
// - the old/new type is not an immutable type. Types are marked as
|
||||||
|
// immutable if gnucash depends on details that would be lost/missing
|
||||||
|
// if changing from/to such a type. At the time of this writing the
|
||||||
|
// immutable types are AR, AP and trading types.
|
||||||
if (xaccAccountCountSplits (aw_get_account (aw), FALSE) > 0)
|
if (xaccAccountCountSplits (aw_get_account (aw), FALSE) > 0)
|
||||||
{
|
{
|
||||||
GNCAccountType atype = xaccAccountGetType (aw_get_account (aw));
|
GNCAccountType atype = xaccAccountGetType (aw_get_account (aw));
|
||||||
GtkWidget *label = gtk_label_new (xaccAccountGetTypeStr (atype));
|
compat_types = xaccAccountTypesCompatibleWith (atype);
|
||||||
GtkWidget *vbox = GTK_WIDGET(gtk_builder_get_object (builder, "type_vbox"));
|
if (!compat_types)
|
||||||
GtkWidget *parent_widget = gtk_widget_get_parent (GTK_WIDGET(aw->type_view));
|
compat_types = xaccAccountTypesValid ();
|
||||||
|
|
||||||
g_object_ref (G_OBJECT(aw->type_view));
|
|
||||||
gtk_container_remove (GTK_CONTAINER(vbox), parent_widget);
|
|
||||||
gtk_widget_set_tooltip_text (label, tt);
|
|
||||||
gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
|
|
||||||
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
|
|
||||||
gtk_widget_show (label);
|
|
||||||
}
|
}
|
||||||
|
gnc_account_type_view_create (aw, compat_types);
|
||||||
|
|
||||||
gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(aw->dialog));
|
gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(aw->dialog));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user