diff --git a/src/app-utils/gnc-ui-util.c b/src/app-utils/gnc-ui-util.c index 54295ee9fb..3b988e6009 100644 --- a/src/app-utils/gnc-ui-util.c +++ b/src/app-utils/gnc-ui-util.c @@ -295,7 +295,7 @@ gnc_book_use_book_currency (QofBook *book) if (!book) return FALSE; policy = qof_book_get_default_gains_policy (book); - currency = qof_book_get_book_currency (book); + currency = qof_book_get_book_currency_name (book); /* If either a default gain/loss policy or a book-currency does not exist, book-currency accounting method not valid */ @@ -303,11 +303,11 @@ gnc_book_use_book_currency (QofBook *book) return FALSE; /* If both exist, both must be valid */ - if (!gnc_valid_policy (policy) || !gnc_commodity_table_lookup - (gnc_commodity_table_get_table - (gnc_get_current_book()), - GNC_COMMODITY_NS_CURRENCY, - currency)) + if (!gnc_valid_policy_name (policy) || !gnc_commodity_table_lookup + (gnc_commodity_table_get_table + (gnc_get_current_book()), + GNC_COMMODITY_NS_CURRENCY, + currency)) return FALSE; /* If both exist and are valid, there must be no trading accounts flag */ @@ -322,12 +322,30 @@ gnc_book_use_book_currency (QofBook *book) * both are valid, a requirement for the 'book-currency' currency accounting * method to apply. */ const gchar * +gnc_book_get_book_currency_name (QofBook *book) +{ + if (!book) return NULL; + + if (gnc_book_use_book_currency (book)) + return qof_book_get_book_currency_name (book); + + return NULL; +} + +/** Returns pointer to Book Currency for book or NULL; determines + * that both book-currency and default gain/loss policy KVPs exist and that + * both are valid, a requirement for the 'book-currency' currency accounting + * method to apply. */ +gnc_commodity * gnc_book_get_book_currency (QofBook *book) { if (!book) return NULL; if (gnc_book_use_book_currency (book)) - return qof_book_get_book_currency (book); + return gnc_commodity_table_lookup + (gnc_commodity_table_get_table(book), + GNC_COMMODITY_NS_CURRENCY, + qof_book_get_book_currency_name (book)); return NULL; } @@ -347,6 +365,24 @@ gnc_book_get_default_gains_policy (QofBook *book) return NULL; } +/** Returns pointer to default gain/loss account for book or NULL; determines + * that both book-currency and default gain/loss policy KVPs exist and that + * both are valid, a requirement for the 'book-currency' currency accounting + * method to apply. */ +Account * +gnc_book_get_default_gain_loss_acct (QofBook *book) +{ + Account *gains_account = NULL; + + if (!book) return NULL; + + if (gnc_book_use_book_currency (book)) + gains_account = xaccAccountLookup + (qof_book_get_default_gain_loss_acct_guid (book), book); + + return gains_account; +} + Account * gnc_get_current_root_account (void) { @@ -995,6 +1031,9 @@ gnc_default_currency_common (gchar *requested_currency, GNC_COMMODITY_NS_CURRENCY, requested_currency); + if (gnc_book_use_book_currency (gnc_get_current_book ())) + return gnc_book_get_book_currency (gnc_get_current_book ()); + if (gnc_prefs_get_bool (section, GNC_PREF_CURRENCY_CHOICE_OTHER)) { mnemonic = gnc_prefs_get_string(section, GNC_PREF_CURRENCY_OTHER); diff --git a/src/app-utils/gnc-ui-util.h b/src/app-utils/gnc-ui-util.h index 79c02db60a..4f616097a3 100644 --- a/src/app-utils/gnc-ui-util.h +++ b/src/app-utils/gnc-ui-util.h @@ -94,7 +94,13 @@ gboolean gnc_book_use_book_currency (QofBook *book); * that both book-currency and default gain/loss policy KVPs exist and that * both are valid, a requirement for the 'book-currency' currency accounting * method to apply. */ -const gchar * gnc_book_get_book_currency (QofBook *book); +const gchar * gnc_book_get_book_currency_name (QofBook *book); + +/** Returns pointer to Book Currency for book or NULL; determines + * that both book-currency and default gain/loss policy KVPs exist and that + * both are valid, a requirement for the 'book-currency' currency accounting + * method to apply. */ +gnc_commodity * gnc_book_get_book_currency (QofBook *book); /** Returns pointer to default gain/loss policy for book or NULL; determines * that both book-currency and default gain/loss policy KVPs exist and that @@ -102,6 +108,12 @@ const gchar * gnc_book_get_book_currency (QofBook *book); * method to apply. */ const gchar * gnc_book_get_default_gains_policy (QofBook *book); +/** Returns pointer to default gain/loss account for book or NULL; determines + * that both book-currency and default gain/loss policy KVPs exist and that + * both are valid, a requirement for the 'book-currency' currency accounting + * method to apply. */ +Account * gnc_book_get_default_gain_loss_acct (QofBook *book); + Account * gnc_get_current_root_account (void); gnc_commodity_table * gnc_get_current_commodities (void); diff --git a/src/app-utils/options.scm b/src/app-utils/options.scm index df2f1956d5..d771680015 100644 --- a/src/app-utils/options.scm +++ b/src/app-utils/options.scm @@ -1441,7 +1441,7 @@ (currency? book-currency-option-path-kvp?)) (if gains-policy-option-path-kvp? - (gnc-valid-policy + (gnc-valid-policy-name gains-policy-option-path-kvp?))) (begin (set! book-currency @@ -1464,7 +1464,7 @@ (if (legal-val (car x) ok-radiobutton-values) (if (eq? 'book-currency (car x)) (if (currency? (currency->scm (cadr x))) - (if (gnc-valid-policy (symbol->string (caddr x))) + (if (gnc-valid-policy-name (symbol->string (caddr x))) (list #t x) (list #f "cap-gains-policy-option: illegal value")) (list #f "currency-option: illegal value")) diff --git a/src/app-utils/test/test-gnc-ui-util.c b/src/app-utils/test/test-gnc-ui-util.c index a6a84cb755..704171fd7e 100644 --- a/src/app-utils/test/test-gnc-ui-util.c +++ b/src/app-utils/test/test-gnc-ui-util.c @@ -26,7 +26,7 @@ #include #include #include -/*#include */ +#include "test-engine-stuff.h" #include "../gnc-ui-util.h" @@ -64,12 +64,15 @@ test_book_use_book_currency( Fixture *fixture, gconstpointer pData ) { const gchar *cur; const gchar *pol; + Account *acct, *acc; g_test_message( "Testing with no currency accounting method selected" ); - cur = gnc_book_get_book_currency( fixture-> book ); + cur = gnc_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , NULL ); pol = gnc_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , NULL ); + acct = gnc_book_get_default_gain_loss_acct ( fixture-> book ); + g_assert (acct == NULL ); g_assert( !gnc_book_use_book_currency ( fixture-> book )); g_test_message( "Testing with trading accounts set to true - t" ); @@ -77,17 +80,19 @@ test_book_use_book_currency( Fixture *fixture, gconstpointer pData ) qof_instance_set (QOF_INSTANCE (fixture->book), "trading-accts", "t", NULL); - cur = gnc_book_get_book_currency( fixture-> book ); + cur = gnc_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , NULL ); pol = gnc_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , NULL ); + acct = gnc_book_get_default_gain_loss_acct ( fixture-> book ); + g_assert (acct == NULL ); g_assert( !gnc_book_use_book_currency ( fixture-> book )); qof_book_commit_edit (fixture->book); qof_book_destroy( fixture->book ); fixture->book = qof_book_new(); - g_test_message( "Testing with valid book-currency but default-gains-policy set to nonsense" ); + g_test_message( "Testing with valid book-currency but default-gains-policy set to nonsense and default-gain-loss-account-guid set to random valid acct" ); qof_book_begin_edit (fixture->book); qof_instance_set (QOF_INSTANCE (fixture->book), "book-currency", "USD", @@ -95,17 +100,23 @@ test_book_use_book_currency( Fixture *fixture, gconstpointer pData ) qof_instance_set (QOF_INSTANCE (fixture->book), "default-gains-policy", "random", NULL); - cur = gnc_book_get_book_currency( fixture-> book ); + acc = get_random_account( fixture-> book ); + qof_instance_set (QOF_INSTANCE (fixture->book), + "default-gain-loss-account-guid", qof_entity_get_guid(QOF_INSTANCE(acc)), + NULL); + cur = gnc_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , NULL ); pol = gnc_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , NULL ); + acct = gnc_book_get_default_gain_loss_acct ( fixture-> book ); + g_assert (acct == NULL ); g_assert( !gnc_book_use_book_currency ( fixture-> book )); qof_book_commit_edit (fixture->book); qof_book_destroy( fixture->book ); fixture->book = qof_book_new(); - g_test_message( "Testing with valid default-gains-policy but book-currency set to nonsense" ); + g_test_message( "Testing with valid default-gains-policy but book-currency set to nonsense and default-gain-loss-account-guid set to random valid acct" ); qof_book_begin_edit (fixture->book); qof_instance_set (QOF_INSTANCE (fixture->book), "book-currency", "myMoney", @@ -113,17 +124,23 @@ test_book_use_book_currency( Fixture *fixture, gconstpointer pData ) qof_instance_set (QOF_INSTANCE (fixture->book), "default-gains-policy", "fifo", NULL); - cur = gnc_book_get_book_currency( fixture-> book ); + acc = get_random_account( fixture-> book ); + qof_instance_set (QOF_INSTANCE (fixture->book), + "default-gain-loss-account-guid", qof_entity_get_guid(QOF_INSTANCE(acc)), + NULL); + cur = gnc_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , NULL ); pol = gnc_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , NULL ); + acct = gnc_book_get_default_gain_loss_acct ( fixture-> book ); + g_assert (acct == NULL ); g_assert( !gnc_book_use_book_currency ( fixture-> book )); qof_book_commit_edit (fixture->book); qof_book_destroy( fixture->book ); fixture->book = qof_book_new(); - g_test_message( "Testing with book-currency and default-gains-policy set to nonsense" ); + g_test_message( "Testing with book-currency and default-gains-policy set to nonsense and default-gain-loss-account-guid set to random valid acct" ); qof_book_begin_edit (fixture->book); qof_instance_set (QOF_INSTANCE (fixture->book), "book-currency", "myMoney", @@ -131,47 +148,65 @@ test_book_use_book_currency( Fixture *fixture, gconstpointer pData ) qof_instance_set (QOF_INSTANCE (fixture->book), "default-gains-policy", "random", NULL); - cur = gnc_book_get_book_currency( fixture-> book ); + acc = get_random_account( fixture-> book ); + qof_instance_set (QOF_INSTANCE (fixture->book), + "default-gain-loss-account-guid", qof_entity_get_guid(QOF_INSTANCE(acc)), + NULL); + cur = gnc_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , NULL ); pol = gnc_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , NULL ); + acct = gnc_book_get_default_gain_loss_acct ( fixture-> book ); + g_assert (acct == NULL ); g_assert( !gnc_book_use_book_currency ( fixture-> book )); qof_book_commit_edit (fixture->book); qof_book_destroy( fixture->book ); fixture->book = qof_book_new(); - g_test_message( "Testing with book-currency set and no default-gains-policy" ); + g_test_message( "Testing with book-currency set and no default-gains-policy and default-gain-loss-account-guid set to random valid acct" ); qof_book_begin_edit (fixture->book); qof_instance_set (QOF_INSTANCE (fixture->book), "book-currency", "USD", NULL); - cur = gnc_book_get_book_currency( fixture-> book ); + acc = get_random_account( fixture-> book ); + qof_instance_set (QOF_INSTANCE (fixture->book), + "default-gain-loss-account-guid", qof_entity_get_guid(QOF_INSTANCE(acc)), + NULL); + cur = gnc_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , NULL ); pol = gnc_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , NULL ); + acct = gnc_book_get_default_gain_loss_acct ( fixture-> book ); + g_assert (acct == NULL ); g_assert( !gnc_book_use_book_currency ( fixture-> book )); qof_book_commit_edit (fixture->book); qof_book_destroy( fixture->book ); fixture->book = qof_book_new(); - g_test_message( "Testing with default-gains-policy set and no book-currency" ); + g_test_message( "Testing with default-gains-policy set and no book-currency and default-gain-loss-account-guid set to random valid acct" ); qof_book_begin_edit (fixture->book); qof_instance_set (QOF_INSTANCE (fixture->book), "default-gains-policy", "fifo", NULL); - cur = gnc_book_get_book_currency( fixture-> book ); + acc = get_random_account( fixture-> book ); + qof_instance_set (QOF_INSTANCE (fixture->book), + "default-gain-loss-account-guid", qof_entity_get_guid(QOF_INSTANCE(acc)), + NULL); + cur = gnc_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , NULL ); pol = gnc_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , NULL ); + acct = gnc_book_get_default_gain_loss_acct ( fixture-> book ); + g_assert (acct == NULL ); g_assert( !gnc_book_use_book_currency ( fixture-> book )); qof_book_commit_edit (fixture->book); qof_book_destroy( fixture->book ); fixture->book = qof_book_new(); - g_test_message( "Testing with book-currency and default-gains-policy set to valid values and with trading accounts set to true - t" ); + g_test_message( "Testing with book-currency, default-gains-policy and default-gain-loss-account-guid set to valid values and with trading accounts set to true - t" ); qof_book_begin_edit (fixture->book); qof_instance_set (QOF_INSTANCE (fixture->book), "trading-accts", "t", @@ -182,17 +217,23 @@ test_book_use_book_currency( Fixture *fixture, gconstpointer pData ) qof_instance_set (QOF_INSTANCE (fixture->book), "default-gains-policy", "fifo", NULL); - cur = gnc_book_get_book_currency( fixture-> book ); + acc = get_random_account( fixture-> book ); + qof_instance_set (QOF_INSTANCE (fixture->book), + "default-gain-loss-account-guid", qof_entity_get_guid(QOF_INSTANCE(acc)), + NULL); + cur = gnc_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , NULL ); pol = gnc_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , NULL ); + acct = gnc_book_get_default_gain_loss_acct ( fixture-> book ); + g_assert (acct == NULL ); g_assert( !gnc_book_use_book_currency ( fixture-> book )); qof_book_commit_edit (fixture->book); qof_book_destroy( fixture->book ); fixture->book = qof_book_new(); - g_test_message( "Testing with book-currency and default-gains-policy set to valid values and no trading accounts flag" ); + g_test_message( "Testing with book-currency, default-gains-policy and default-gain-loss-account-guid set to valid values and no trading accounts flag" ); qof_book_begin_edit (fixture->book); qof_instance_set (QOF_INSTANCE (fixture->book), "book-currency", "USD", @@ -200,10 +241,16 @@ test_book_use_book_currency( Fixture *fixture, gconstpointer pData ) qof_instance_set (QOF_INSTANCE (fixture->book), "default-gains-policy", "fifo", NULL); - cur = gnc_book_get_book_currency( fixture-> book ); + acc = get_random_account( fixture-> book ); + qof_instance_set (QOF_INSTANCE (fixture->book), + "default-gain-loss-account-guid", qof_entity_get_guid(QOF_INSTANCE(acc)), + NULL); + cur = gnc_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , "USD" ); pol = gnc_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , "fifo" ); + acct = gnc_book_get_default_gain_loss_acct ( fixture-> book ); + g_assert ( xaccAccountEqual(acct, acc, TRUE) ); g_assert( gnc_book_use_book_currency ( fixture-> book )); qof_book_commit_edit (fixture->book); } diff --git a/src/engine/policy-p.h b/src/engine/policy-p.h index 76cd97e0ac..0ca7b04bc6 100644 --- a/src/engine/policy-p.h +++ b/src/engine/policy-p.h @@ -63,6 +63,9 @@ struct gncpolicy_s { + char *name; + char *description; + char *hint; GNCLot * (*PolicyGetLot) (GNCPolicy *, Split *split); Split * (*PolicyGetSplit) (GNCPolicy *, GNCLot *lot); void (*PolicyGetLotOpening) (GNCPolicy *, GNCLot *lot, diff --git a/src/engine/policy.c b/src/engine/policy.c index 38da2058bf..b66c84c854 100644 --- a/src/engine/policy.c +++ b/src/engine/policy.c @@ -67,38 +67,22 @@ GList * gnc_get_valid_policy_list (void) { GList *return_list = NULL; - GList *policy_list1 = NULL; - GList *policy_list2 = NULL; - GList *policy_list3 = NULL; - GList *policy_list4 = NULL; - policy_list1 = g_list_prepend (policy_list1, MANUAL_POLICY_HINT); - policy_list1 = g_list_prepend (policy_list1, MANUAL_POLICY_DESC); - policy_list1 = g_list_prepend (policy_list1, MANUAL_POLICY); - return_list = g_list_prepend (return_list, policy_list1); - policy_list2 = g_list_prepend (policy_list2, AVERAGE_POLICY_HINT); - policy_list2 = g_list_prepend (policy_list2, AVERAGE_POLICY_DESC); - policy_list2 = g_list_prepend (policy_list2, AVERAGE_POLICY); - return_list = g_list_prepend (return_list, policy_list2); - policy_list3 = g_list_prepend (policy_list3, LIFO_POLICY_HINT); - policy_list3 = g_list_prepend (policy_list3, LIFO_POLICY_DESC); - policy_list3 = g_list_prepend (policy_list3, LIFO_POLICY); - return_list = g_list_prepend (return_list, policy_list3); - policy_list4 = g_list_prepend (policy_list4, FIFO_POLICY_HINT); - policy_list4 = g_list_prepend (policy_list4, FIFO_POLICY_DESC); - policy_list4 = g_list_prepend (policy_list4, FIFO_POLICY); - return_list = g_list_prepend (return_list, policy_list4); +/* return_list = g_list_prepend (return_list, xaccGetManualPolicy()); + return_list = g_list_prepend (return_list, xaccGetAveragePolicy()); */ + return_list = g_list_prepend (return_list, xaccGetLIFOPolicy()); + return_list = g_list_prepend (return_list, xaccGetFIFOPolicy()); return return_list; } gboolean -gnc_valid_policy (const gchar *name) +gnc_valid_policy_name (const gchar *policy_name) { GList *list_of_policies = NULL; gboolean ret_val = FALSE; - if (!name) + if (!policy_name) return ret_val; list_of_policies = gnc_get_valid_policy_list(); @@ -111,13 +95,12 @@ gnc_valid_policy (const gchar *name) GList *l = NULL; for (l = list_of_policies; l != NULL; l = l->next) { - GList *policy_list = l->data; - if (g_strcmp0(policy_list->data, name) == 0) + GNCPolicy *list_pcy = l->data; + if (g_strcmp0(PolicyGetName (list_pcy), policy_name) == 0) ret_val = TRUE; - g_list_free(policy_list); } g_list_free(list_of_policies); - return ret_val; + return ret_val; } } @@ -208,6 +191,26 @@ donext: return NULL; } +const char * +PolicyGetName (const GNCPolicy *pcy) +{ + if(!pcy) return NULL; + return pcy->name; +} + +const char * +PolicyGetDescription (const GNCPolicy *pcy) +{ + if(!pcy) return NULL; + return pcy->description; +} +const char * +PolicyGetHint (const GNCPolicy *pcy) +{ + if(!pcy) return NULL; + return pcy->hint; +} + /* ============================================================== */ static GNCLot * @@ -246,11 +249,6 @@ FIFOPolicyIsOpeningSplit (GNCPolicy *pcy, GNCLot *lot, Split *split) return (split == opening_split); } -/* ============================================================== */ -/* Define a single, static policy, since we have no per-object data. - * I suppose this could change, but we don't need any better at the - * moment ... */ - GNCPolicy * xaccGetFIFOPolicy (void) { @@ -259,6 +257,9 @@ xaccGetFIFOPolicy (void) if (!pcy) { pcy = g_new (GNCPolicy, 1); + pcy->name = FIFO_POLICY; + pcy->description = FIFO_POLICY_DESC; + pcy->hint = FIFO_POLICY_HINT; pcy->PolicyGetLot = FIFOPolicyGetLot; pcy->PolicyGetSplit = FIFOPolicyGetSplit; pcy->PolicyGetLotOpening = FIFOPolicyGetLotOpening; @@ -267,12 +268,7 @@ xaccGetFIFOPolicy (void) return pcy; } -/* ============================================================== */ -/* Stab at implementing the LIFO policy. This is untested. - * I'm not sure I got it right. - */ - -G_GNUC_UNUSED static GNCLot * +static GNCLot * LIFOPolicyGetLot (GNCPolicy *pcy, Split *split) { if (!split) return NULL; @@ -280,14 +276,14 @@ LIFOPolicyGetLot (GNCPolicy *pcy, Split *split) split->parent->common_currency); } -G_GNUC_UNUSED static Split * +static Split * LIFOPolicyGetSplit (GNCPolicy *pcy, GNCLot *lot) { return DirectionPolicyGetSplit (pcy, lot, 1); } /* This routine is actually identical to FIFO... */ -G_GNUC_UNUSED static void +static void LIFOPolicyGetLotOpening (GNCPolicy *pcy, GNCLot *lot, gnc_numeric *ret_amount, gnc_numeric *ret_value, @@ -302,7 +298,7 @@ LIFOPolicyGetLotOpening (GNCPolicy *pcy, } /* This routine is actually identical to FIFO... */ -G_GNUC_UNUSED static gboolean +static gboolean LIFOPolicyIsOpeningSplit (GNCPolicy *pcy, GNCLot *lot, Split *split) { Split *opening_split; @@ -310,4 +306,23 @@ LIFOPolicyIsOpeningSplit (GNCPolicy *pcy, GNCLot *lot, Split *split) return (split == opening_split); } +GNCPolicy * +xaccGetLIFOPolicy (void) +{ + static GNCPolicy *pcy = NULL; + + if (!pcy) + { + pcy = g_new (GNCPolicy, 1); + pcy->name = LIFO_POLICY; + pcy->description = LIFO_POLICY_DESC; + pcy->hint = LIFO_POLICY_HINT; + pcy->PolicyGetLot = LIFOPolicyGetLot; + pcy->PolicyGetSplit = LIFOPolicyGetSplit; + pcy->PolicyGetLotOpening = LIFOPolicyGetLotOpening; + pcy->PolicyIsOpeningSplit = LIFOPolicyIsOpeningSplit; + } + return pcy; +} + /* =========================== END OF FILE ======================= */ diff --git a/src/engine/policy.h b/src/engine/policy.h index 5c4ad8ca6c..42dc812ce7 100644 --- a/src/engine/policy.h +++ b/src/engine/policy.h @@ -40,21 +40,22 @@ typedef struct gncpolicy_s GNCPolicy; /** Valid Policy List - * Provides a glist of glists for implemented policies. For each implemented - * policy, this glist contains: name, description, hint, as follows: - * glist( - * glist("fifo", "First In First Out", "Use oldest lots first.") - * glist("lifo", "Last In First Out", "Use newest lots first.") - * etc. - * ) - * Both levels of lists must be freed with g_list_free(). + * Provides a glist of implemented policies. + * + * List must be freed with g_list_free(). */ GList * gnc_get_valid_policy_list (void); -/** Valid Policy +/** Valid Policy Name * Uses the Valid Policy List to determine if a policy name is valid. */ -gboolean gnc_valid_policy (const gchar *name); +gboolean gnc_valid_policy_name (const gchar *policy_name); + +const char *PolicyGetName (const GNCPolicy *pcy); + +const char *PolicyGetDescription (const GNCPolicy *pcy); + +const char *PolicyGetHint (const GNCPolicy *pcy); /** First-in, First-out Policy * This policy will create FIFO Lots. FIFO Lots have the following @@ -64,10 +65,24 @@ gboolean gnc_valid_policy (const gchar *name); * -- Splits are added to the lot in date order, with earliest splits * added first. * -- All splits in the lot share the same transaction currency as - * the split that opened the lot. + * the split that opened the lot (if book-currency book option + * selected, this will always be book currency). */ GNCPolicy *xaccGetFIFOPolicy (void); +/** Last-in, Last-out Policy + * This policy will create LIFO Lots. LIFO Lots have the following + * properties: + * -- The lot is started with the latest posted split that isn't + * a part of another lot already. + * -- Splits are added to the lot in date order, with latest splits + * added first. + * -- All splits in the lot share the same transaction currency as + * the split that opened the lot (if book-currency book option + * selected, this will always be book currency). + */ +GNCPolicy *xaccGetLIFOPolicy (void); + #endif /* XACC_POLICY_H */ /** @} */ /** @} */ diff --git a/src/gnome-utils/dialog-options.c b/src/gnome-utils/dialog-options.c index 8c4cb6234b..f75ca53fac 100644 --- a/src/gnome-utils/dialog-options.c +++ b/src/gnome-utils/dialog-options.c @@ -571,8 +571,8 @@ gnc_option_currency_accounting_set_sensitivity(GNCOption *option, for (l = list_of_policies; l != NULL; l = l->next) { /* First item in policy_list is internal name of policy */ - GList *policy_list = l->data; - if (g_strcmp0(policy_list->data, + GNCPolicy *pcy = l->data; + if (g_strcmp0(PolicyGetName (pcy), gnc_scm_symbol_to_locale_string(list_symbol)) == 0) { @@ -581,7 +581,6 @@ gnc_option_currency_accounting_set_sensitivity(GNCOption *option, GNC_COMBOTT(default_cost_policy_widget), i); } i++; - g_list_free(policy_list); } g_list_free(list_of_policies); } @@ -869,17 +868,12 @@ gnc_option_create_currency_accounting_widget (char *name, GNCOption *option) GtkWidget *frame = NULL, *vbox1 = NULL; GtkWidget *widget = NULL; int num_values; - GList *list_of_policies = NULL; int i; num_values = gnc_option_num_permissible_values(option); g_return_val_if_fail(num_values == 3, NULL); - list_of_policies = gnc_get_valid_policy_list(); - - g_return_val_if_fail(g_list_length (list_of_policies) >= 0, NULL); - /* Create our button frame */ frame = gtk_frame_new (name); @@ -915,7 +909,7 @@ gnc_option_create_currency_accounting_widget (char *name, GNCOption *option) { GtkWidget *widget_label; GtkWidget *book_currency_widget = NULL, - *default_cost_policy_widget = NULL; + *default_cost_policy_widget = gnc_cost_policy_select_new(); g_signal_connect(G_OBJECT(widget), "toggled", @@ -934,46 +928,8 @@ gnc_option_create_currency_accounting_widget (char *name, GNCOption *option) gtk_box_pack_start (GTK_BOX (vbox2), book_currency_widget, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0); - if (list_of_policies) + if (default_cost_policy_widget) { - GtkListStore *store; - GtkTreeIter iter; - char *itemstring; - char *description; - GList *l = NULL; - - store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); - /* Add values to the list store, entry and tooltip */ - for (l = list_of_policies; l != NULL; l = l->next) - { - GList *policy_list = l->data; - /* First item in policy_list is internal name of policy */ - policy_list = policy_list->next; - /* Second item in policy_list is policy description */ - itemstring = policy_list->data; - policy_list = policy_list->next; - /* Third item in policy_list is policy hint */ - description = policy_list->data; - gtk_list_store_append (store, &iter); - gtk_list_store_set - (store, - &iter, - 0, - (itemstring && *itemstring) ? _(itemstring) : "", - 1, - (description && *description) ? _(description) : "", - -1); - g_list_free(policy_list); - } - g_list_free(list_of_policies); - /* Create the new Combo with tooltip and add the store */ - default_cost_policy_widget = GTK_WIDGET(gnc_combott_new()); - g_object_set( G_OBJECT( default_cost_policy_widget ), - "model", - GTK_TREE_MODEL(store), - NULL ); - g_object_unref(store); - g_signal_connect(G_OBJECT(default_cost_policy_widget), "changed", G_CALLBACK(gnc_option_multichoice_cb), option); } @@ -3089,8 +3045,9 @@ gnc_option_set_ui_value_currency_accounting (GNCOption *option, { /* First item in policy_list is internal name of policy */ - GList *policy_list = l->data; - if (g_strcmp0(policy_list->data, + GNCPolicy *pcy = l->data; + + if (g_strcmp0(PolicyGetName (pcy), gnc_scm_symbol_to_locale_string(list_symbol)) == 0) { @@ -3101,7 +3058,6 @@ gnc_option_set_ui_value_currency_accounting (GNCOption *option, i); } i++; - g_list_free(policy_list); } g_list_free(list_of_policies); } @@ -3470,11 +3426,10 @@ gnc_option_get_ui_value_currency_accounting (GNCOption *option, GtkWidget *widge gint i = 0; for (l = list_of_policies; l != NULL; l = l->next) { - GList *policy_list = l->data; + GNCPolicy *pcy = l->data; if(i == policy_index) - str = policy_list->data; + str = PolicyGetName (pcy); i++; - g_list_free(policy_list); } g_list_free(list_of_policies); } diff --git a/src/gnome-utils/dialog-utils.c b/src/gnome-utils/dialog-utils.c index 40959c98ca..0f26d4a3f7 100644 --- a/src/gnome-utils/dialog-utils.c +++ b/src/gnome-utils/dialog-utils.c @@ -40,6 +40,7 @@ #include "gnc-euro.h" #include "gnc-ui-util.h" #include "gnc-prefs.h" +#include "gnc-combott.h" #include "guile-util.h" #include "gnc-main-window.h" #include @@ -580,8 +581,8 @@ gnc_dialog_run (GtkDialog *dialog, const gchar *pref_name) /* If this is a new book, this function can be used to display book options * dialog so user can specify options, before any transactions can be - * imported/entered, since they can affect how transactions are created - * Note: This dialog is modal! */ + * imported/entered, since the book options can affect how transactions are + * created. Note: This dialog is modal! */ gboolean gnc_new_book_option_display (GtkWidget *parent) { @@ -603,3 +604,52 @@ gnc_new_book_option_display (GtkWidget *parent) } return TRUE; } + +/* This function returns a widget for selecting a cost policy + */ +GtkWidget * +gnc_cost_policy_select_new (void) +{ + GtkWidget *cost_policy_widget = NULL; + GList *list_of_policies = NULL; + + list_of_policies = gnc_get_valid_policy_list(); + + g_return_val_if_fail(g_list_length (list_of_policies) >= 0, NULL); + if (list_of_policies) + { + GtkListStore *store; + GtkTreeIter iter; + const char *description; + const char *hintstring; + GList *l = NULL; + + store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); + /* Add values to the list store, entry and tooltip */ + for (l = list_of_policies; l != NULL; l = l->next) + { + GNCPolicy *pcy = l->data; + description = PolicyGetDescription(pcy); + hintstring = PolicyGetHint(pcy); + gtk_list_store_append (store, &iter); + gtk_list_store_set + (store, + &iter, + 0, + (description && *description) ? _(description) : "", + 1, + (hintstring && *hintstring) ? _(hintstring) : "", + -1); + } + g_list_free(list_of_policies); + /* Create the new Combo with tooltip and add the store */ + cost_policy_widget = GTK_WIDGET(gnc_combott_new()); + g_object_set( G_OBJECT( cost_policy_widget ), + "model", + GTK_TREE_MODEL(store), + NULL ); + g_object_unref(store); + } + return cost_policy_widget; +} + diff --git a/src/gnome-utils/dialog-utils.h b/src/gnome-utils/dialog-utils.h index 7c14783cca..30a29fa896 100644 --- a/src/gnome-utils/dialog-utils.h +++ b/src/gnome-utils/dialog-utils.h @@ -101,8 +101,13 @@ gnc_dialog_run(GtkDialog *dialog, const gchar *pref_key); /* If this is a new book, this function can be used to display book options * dialog so user can specify options, before any transactions can be - * imported/entered, since they can affect how transactions are created - * Note: This dialog is modal! */ + * imported/entered, since the book options can affect how transactions are + * created. Note: This dialog is modal! */ gboolean gnc_new_book_option_display (GtkWidget *parent); +/** This function returns a widget for selecting a cost policy + */ +GtkWidget * +gnc_cost_policy_select_new (void); + #endif /* DIALOG_UTILS_H */ diff --git a/src/libqof/qof/qofbook.cpp b/src/libqof/qof/qofbook.cpp index 5a9a6db4b8..e5f3ad9fe1 100644 --- a/src/libqof/qof/qofbook.cpp +++ b/src/libqof/qof/qofbook.cpp @@ -69,17 +69,22 @@ enum PROP_0, // PROP_ROOT_ACCOUNT, /* Table */ // PROP_ROOT_TEMPLATE, /* Table */ -/* keep trading accounts property, while adding book-currency and default - gains properties, so that files prior to 2.7 can be read/processed; GUI - changed to use all three properties as of 2.7. Trading accounts, on the - one hand, and book-currency plus default-gains-policy, on the other, - are mutually exclusive */ +/* keep trading accounts property, while adding book-currency, default gains + policy and default gains account properties, so that files prior to 2.7 can + be read/processed; GUI changed to use all four properties as of 2.7. + Trading accounts, on the one hand, and book-currency plus default-gains- + policy, and optionally, default gains account, on the other, are mutually + exclusive */ PROP_OPT_TRADING_ACCOUNTS, /* KVP */ -/* Book currency and default gains properties only apply if currency +/* Book currency and default gains policy properties only apply if currency accounting method selected in GUI is 'book-currency'; both required and both are exclusive with trading accounts */ PROP_OPT_BOOK_CURRENCY, /* KVP */ PROP_OPT_DEFAULT_GAINS_POLICY, /* KVP */ +/* Default gains account property only applies if currency accounting method + selected in GUI is 'book-currency'; its use is optional but exclusive with + trading accounts */ + PROP_OPT_DEFAULT_GAINS_ACCOUNT_GUID, /* KVP */ PROP_OPT_AUTO_READONLY_DAYS,/* KVP */ PROP_OPT_NUM_FIELD_SOURCE, /* KVP */ PROP_OPT_DEFAULT_BUDGET, /* KVP */ @@ -158,6 +163,13 @@ qof_book_get_property (GObject* object, qof_instance_get_kvp (QOF_INSTANCE (book), key, value); g_free (key); break; + case PROP_OPT_DEFAULT_GAINS_ACCOUNT_GUID: + key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH, + OPTION_SECTION_ACCOUNTS, + OPTION_NAME_DEFAULT_GAINS_LOSS_ACCT_GUID); + qof_instance_get_kvp (QOF_INSTANCE (book), key, value); + g_free (key); + break; case PROP_OPT_AUTO_READONLY_DAYS: key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH, OPTION_SECTION_ACCOUNTS, @@ -229,6 +241,13 @@ qof_book_set_property (GObject *object, qof_instance_set_kvp (QOF_INSTANCE (book), key, value); g_free (key); break; + case PROP_OPT_DEFAULT_GAINS_ACCOUNT_GUID: + key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH, + OPTION_SECTION_ACCOUNTS, + OPTION_NAME_DEFAULT_GAINS_LOSS_ACCT_GUID); + qof_instance_set_kvp (QOF_INSTANCE (book), key, value); + g_free (key); + break; case PROP_OPT_AUTO_READONLY_DAYS: key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH, OPTION_SECTION_ACCOUNTS, @@ -307,6 +326,18 @@ qof_book_class_init (QofBookClass *klass) NULL, G_PARAM_READWRITE)); + g_object_class_install_property + (gobject_class, + PROP_OPT_DEFAULT_GAINS_ACCOUNT_GUID, + g_param_spec_boxed("default-gain-loss-account-guid", + "Select Default Gain/Loss Account", + "The default account to be used for calculated gains/losses on " + "dispositions of currencies/commodities other than " + "'book-currency' when 'book-currency' currency accounting " + "method selected; requires valid book-currency.", + GNC_TYPE_GUID, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, PROP_OPT_NUM_FIELD_SOURCE, @@ -951,35 +982,15 @@ qof_book_normalize_counter_format_internal(const gchar *p, * KVP, or NULL; does not validate contents nor determine if there is a valid * default gain/loss policy, both of which are required, for the * 'book-currency' currency accounting method to apply. Use instead - * 'gnc_book_get_book_currency' which does these validations. */ + * 'gnc_book_get_book_currency_name' which does these validations. */ const gchar * -qof_book_get_book_currency (QofBook *book) +qof_book_get_book_currency_name (QofBook *book) { - KvpFrame *kvp; - KvpValue *value; - - if (!book) - { - PWARN ("No book!!!"); - return NULL; - } - - /* Get the KVP from the current book */ - kvp = qof_instance_get_slots (QOF_INSTANCE (book)); - - if (!kvp) - { - PWARN ("Book has no KVP_Frame"); - return NULL; - } - - /* See if there is a book currency. */ - value = kvp->get_slot({KVP_OPTION_PATH, OPTION_SECTION_ACCOUNTS, - OPTION_NAME_BOOK_CURRENCY}); - if (!value) /* No book-currency */ - return nullptr; - - return value->get(); + const gchar *opt = NULL; + qof_instance_get (QOF_INSTANCE (book), + "book-currency", &opt, + NULL); + return opt; } /** Returns pointer to default gain/loss policy for book, if one exists in the @@ -990,35 +1001,28 @@ qof_book_get_book_currency (QofBook *book) const gchar * qof_book_get_default_gains_policy (QofBook *book) { - KvpFrame *kvp; - KvpValue *value; - - if (!book) - { - PWARN ("No book!!!"); - return NULL; - } - - /* Get the KVP from the current book */ - kvp = qof_instance_get_slots (QOF_INSTANCE (book)); - - if (!kvp) - { - PWARN ("Book has no KVP_Frame"); - return NULL; - } - - /* See if there is a default gain/loss policy */ - value = kvp->get_slot({KVP_OPTION_PATH, OPTION_SECTION_ACCOUNTS, - OPTION_NAME_DEFAULT_GAINS_POLICY}); - if (!value) - /* No default gain/loss policy, therefore not valid book-currency - accounting method */ - return nullptr; - - return g_strdup(value->get()); + const gchar *opt = NULL; + qof_instance_get (QOF_INSTANCE (book), + "default-gains-policy", &opt, + NULL); + return opt; } +/** Returns pointer to default gain/loss account GUID for book, if one exists in + * the KVP, or NULL; does not validate contents nor determine if there is a + * valid book-currency, both of which are required, for the 'book-currency' + * currency accounting method to apply. Use instead + * 'gnc_book_get_default_gain_loss_acct' which does these validations. */ +const GncGUID * +qof_book_get_default_gain_loss_acct_guid (QofBook *book) +{ + GncGUID *guid = NULL; + qof_instance_get (QOF_INSTANCE (book), + "default-gain-loss-account-guid", &guid, + NULL); + return guid; + +} /* Determine whether this book uses trading accounts */ gboolean diff --git a/src/libqof/qof/qofbook.h b/src/libqof/qof/qofbook.h index f18a1ea52b..547f6b3b5b 100644 --- a/src/libqof/qof/qofbook.h +++ b/src/libqof/qof/qofbook.h @@ -253,8 +253,8 @@ gboolean qof_book_use_trading_accounts (const QofBook *book); * KVP, or NULL; does not validate contents nor determine if there is a valid * default gain/loss policy, both of which are required, for the * 'book-currency' currency accounting method to apply. Use instead - * 'gnc_book_get_book_currency' which does these validations. */ -const gchar * qof_book_get_book_currency (QofBook *book); + * 'gnc_book_get_book_currency_name' which does these validations. */ +const gchar * qof_book_get_book_currency_name (QofBook *book); /** Returns pointer to default gain/loss policy for book, if one exists in the * KVP, or NULL; does not validate contents nor determine if there is a valid @@ -263,6 +263,13 @@ const gchar * qof_book_get_book_currency (QofBook *book); * 'gnc_book_get_default_gains_policy' which does these validations. */ const gchar * qof_book_get_default_gains_policy (QofBook *book); +/** Returns pointer to default gain/loss account GUID for book, if one exists in + * the KVP, or NULL; does not validate contents nor determine if there is a + * valid book-currency, both of which are required, for the 'book-currency' + * currency accounting method to apply. Use instead + * 'gnc_book_get_default_gain_loss_acct' which does these validations. */ +const GncGUID * qof_book_get_default_gain_loss_acct_guid (QofBook *book); + /** Returns TRUE if the auto-read-only feature should be used, otherwise * FALSE. This is just a wrapper on qof_book_get_num_days_autoreadonly() == 0. */ gboolean qof_book_uses_autoreadonly (const QofBook *book); diff --git a/src/libqof/qof/qofbookslots.h b/src/libqof/qof/qofbookslots.h index f820fd3c09..10e1d6450b 100644 --- a/src/libqof/qof/qofbookslots.h +++ b/src/libqof/qof/qofbookslots.h @@ -67,6 +67,7 @@ #define OPTION_NAME_CURRENCY_ACCOUNTING N_("Currency Accounting") #define OPTION_NAME_BOOK_CURRENCY N_("Book Currency") #define OPTION_NAME_DEFAULT_GAINS_POLICY N_("Default Gains Policy") +#define OPTION_NAME_DEFAULT_GAINS_LOSS_ACCT_GUID N_("Default Gain or Loss Account") #define OPTION_NAME_AUTO_READONLY_DAYS N_("Day Threshold for Read-Only Transactions (red line)") #define OPTION_NAME_NUM_FIELD_SOURCE N_("Use Split Action Field for Number") @@ -82,6 +83,7 @@ * OPTION-NAME-CURRENCY-ACCOUNTING * OPTION-NAME-BOOK-CURRENCY * OPTION_NAME_DEFAULT_GAINS_POLICY + * OPTION_NAME_DEFAULT_GAINS_LOSS_ACCT_GUID * OPTION-NAME-AUTO-READONLY-DAYS * OPTION-NAME_NUM-FIELD-SOURCE * OPTION-SECTION-BUDGETING diff --git a/src/libqof/qof/test/test-qofbook.c b/src/libqof/qof/test/test-qofbook.c index cc31369035..ee086a1fbe 100644 --- a/src/libqof/qof/test/test-qofbook.c +++ b/src/libqof/qof/test/test-qofbook.c @@ -460,35 +460,43 @@ test_book_use_book_currency( Fixture *fixture, gconstpointer pData ) { const gchar *cur; const gchar *pol; + GncGUID *acct; + const GncGUID *acct2; - cur = qof_book_get_book_currency( fixture-> book ); + cur = qof_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , NULL ); pol = qof_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , NULL ); + acct2 = qof_book_get_default_gain_loss_acct_guid( fixture-> book ); + g_assert (acct2 == NULL ); g_test_message( "Testing with existing trading accounts set to true - t" ); qof_book_begin_edit (fixture->book); qof_instance_set (QOF_INSTANCE (fixture->book), "trading-accts", "t", NULL); - cur = qof_book_get_book_currency( fixture-> book ); + cur = qof_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , NULL ); pol = qof_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , NULL ); + acct2 = qof_book_get_default_gain_loss_acct_guid( fixture-> book ); + g_assert (acct2 == NULL ); qof_book_commit_edit (fixture->book); qof_book_destroy( fixture->book ); fixture->book = qof_book_new(); - g_test_message( "Testing with book-currency set and no default-gains-policy" ); + g_test_message( "Testing with book-currency set and no default-gains-policy or account" ); qof_book_begin_edit (fixture->book); qof_instance_set (QOF_INSTANCE (fixture->book), "book-currency", "USD", NULL); - cur = qof_book_get_book_currency( fixture-> book ); + cur = qof_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , "USD" ); pol = qof_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , NULL ); + acct2 = qof_book_get_default_gain_loss_acct_guid( fixture-> book ); + g_assert (acct2 == NULL ); qof_book_commit_edit (fixture->book); qof_book_destroy( fixture->book ); @@ -499,10 +507,12 @@ test_book_use_book_currency( Fixture *fixture, gconstpointer pData ) qof_instance_set (QOF_INSTANCE (fixture->book), "default-gains-policy", "fifo", NULL); - cur = qof_book_get_book_currency( fixture-> book ); + cur = qof_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , NULL ); pol = qof_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , "fifo" ); + acct2 = qof_book_get_default_gain_loss_acct_guid( fixture-> book ); + g_assert (acct2 == NULL ); qof_book_commit_edit (fixture->book); qof_book_destroy( fixture->book ); @@ -516,16 +526,18 @@ test_book_use_book_currency( Fixture *fixture, gconstpointer pData ) qof_instance_set (QOF_INSTANCE (fixture->book), "default-gains-policy", "random", NULL); - cur = qof_book_get_book_currency( fixture-> book ); + cur = qof_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , "myMoney" ); pol = qof_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , "random" ); + acct2 = qof_book_get_default_gain_loss_acct_guid( fixture-> book ); + g_assert (acct2 == NULL ); qof_book_commit_edit (fixture->book); qof_book_destroy( fixture->book ); fixture->book = qof_book_new(); - g_test_message( "Testing with book-currency and default-gains-policy set to valid values" ); + g_test_message( "Testing with book-currency, default-gains-policy and default-gains-account set to valid values" ); qof_book_begin_edit (fixture->book); qof_instance_set (QOF_INSTANCE (fixture->book), "book-currency", "USD", @@ -533,10 +545,18 @@ test_book_use_book_currency( Fixture *fixture, gconstpointer pData ) qof_instance_set (QOF_INSTANCE (fixture->book), "default-gains-policy", "fifo", NULL); - cur = qof_book_get_book_currency( fixture-> book ); + acct = guid_new(); + qof_instance_set (QOF_INSTANCE (fixture->book), + "default-gain-loss-account-guid", acct, + NULL); + cur = qof_book_get_book_currency_name( fixture-> book ); g_assert_cmpstr( cur, == , "USD" ); pol = qof_book_get_default_gains_policy( fixture-> book ); g_assert_cmpstr( pol, == , "fifo" ); + acct2 = qof_book_get_default_gain_loss_acct_guid( fixture-> book ); + g_assert_cmpstr( guid_to_string (acct), == , guid_to_string (acct2) ); + g_assert (guid_equal(acct, acct2)); + guid_free (acct); qof_book_commit_edit (fixture->book); }