diff --git a/src/engine/Account.c b/src/engine/Account.c index 3db7c5676d..bf73c16143 100644 --- a/src/engine/Account.c +++ b/src/engine/Account.c @@ -103,6 +103,7 @@ xaccInitAccount (Account * acc) xaccGUIDNew(&acc->guid); xaccStoreEntity(acc, &acc->guid, GNC_ID_ACCOUNT); + LEAVE ("guid=%s\n", guid_to_string(&acc->guid)); } /********************************************************************\ @@ -341,6 +342,7 @@ xaccAccountSetGUID (Account *account, GUID *guid) { if (!account || !guid) return; + PINFO("acct=%p guid=%s", account, guid_to_string(guid)); xaccRemoveEntity(&account->guid); account->guid = *guid; @@ -968,6 +970,50 @@ update_split_currency(Account * acc) { } } +/********************************************************************\ +\********************************************************************/ +/* This is an experimental implementation of set commodity. In the + * long haul, it will need to set the one and only commodity field. + * But in the interim phase, we try to guess right ... + */ + +void +xaccAccountSetCommodity (Account * acc, const gnc_commodity * com) +{ + if ((!acc) || (!com)) return; + if (!acc->currency) + { + xaccAccountSetCurrency (acc, com); + if (acc->security) + { + PWARN ("security was set, but currency wasn't"); + } + return; + } + + if (gnc_commodity_equiv(com, acc->currency)) return; + + if (!acc->security) + { + xaccAccountSetSecurity (acc, com); + return; + } + + if (gnc_commodity_equiv(com, acc->security)) return; + + PWARN ("unexpected, don't know what to do\n" + "\tacc->currecny=%s\n" + "\tacc->security=%s\n" + "\tset commodity=%s\n", + gnc_commodity_get_unique_name (acc->currency), + gnc_commodity_get_unique_name (acc->security), + gnc_commodity_get_unique_name (com)); +} + +/********************************************************************\ +\********************************************************************/ +/* below follow the old, deprecated currency/security routines. */ + void xaccAccountSetCurrency (Account * acc, const gnc_commodity * currency) { diff --git a/src/engine/Account.h b/src/engine/Account.h index 50ca7d91f9..c6a3fd6c18 100644 --- a/src/engine/Account.h +++ b/src/engine/Account.h @@ -191,6 +191,31 @@ void xaccAccountSetName (Account *account, const char *name); void xaccAccountSetCode (Account *account, const char *code); void xaccAccountSetDescription (Account *account, const char *desc); void xaccAccountSetNotes (Account *account, const char *notes); + +GNCAccountType xaccAccountGetType (Account *account); +const char * xaccAccountGetName (Account *account); +const char * xaccAccountGetCode (Account *account); +const char * xaccAccountGetDescription (Account *account); +const char * xaccAccountGetNotes (Account *account); + +/* New commodity access routines. + * In the near future, there will only be one commodity associated + * with an account, rather than two. Use the + * xaccAccountSetCommodity() and xaccAccountGetCommodity() + * routines to set and fetch it. + * + * Basically, the next version of the engine will eliminate the + * 'currency' field of the Account structure. Instead, the common + * currency will be stored with the transaction. This will + * vastly simplify inter-account transfers. + */ +#define xaccAccountGetCommodity xaccAccountGetEffectiveSecurity +void xaccAccountSetCommodity (Account *account, const gnc_commodity *comm); + +/* Soon-to-be-deprecated currency/security access routines. + * The future API will associate only one thing with an account: + * the 'commodity'. Use xaccAccountGetCommodity() to fetch it. + */ void xaccAccountSetCurrency (Account *account, const gnc_commodity *currency); void xaccAccountSetSecurity (Account *account, const gnc_commodity *security); void xaccAccountSetCurrencySCU (Account *account, int frac); @@ -198,11 +223,6 @@ void xaccAccountSetSecuritySCU (Account *account, int frac); int xaccAccountGetCurrencySCU (Account *account); int xaccAccountGetSecuritySCU (Account *account); -GNCAccountType xaccAccountGetType (Account *account); -const char * xaccAccountGetName (Account *account); -const char * xaccAccountGetCode (Account *account); -const char * xaccAccountGetDescription (Account *account); -const char * xaccAccountGetNotes (Account *account); const gnc_commodity * xaccAccountGetCurrency (Account *account); const gnc_commodity * xaccAccountGetSecurity (Account *account); const gnc_commodity * xaccAccountGetEffectiveSecurity (Account *account); diff --git a/src/engine/Transaction.c b/src/engine/Transaction.c index 6753f0e735..4b0b164613 100644 --- a/src/engine/Transaction.c +++ b/src/engine/Transaction.c @@ -555,6 +555,7 @@ xaccInitTransaction (Transaction * trans) trans->num = g_cache_insert(gnc_string_cache, ""); trans->description = g_cache_insert(gnc_string_cache, ""); + trans->common_currency = NULL; trans->splits = NULL; trans->date_entered.tv_sec = 0; @@ -1096,7 +1097,7 @@ FindCommonCurrency (GList *splits, const gnc_commodity * xaccTransFindCommonCurrency (Transaction *trans) { - const gnc_commodity * ra, * rb; + const gnc_commodity *ra, *rb, *retval; Split *split; if (!trans) return NULL; @@ -1110,7 +1111,21 @@ xaccTransFindCommonCurrency (Transaction *trans) ra = xaccAccountGetCurrency (split->acc); rb = xaccAccountGetSecurity (split->acc); - return FindCommonCurrency (trans->splits, ra, rb); + retval = FindCommonCurrency (trans->splits, ra, rb); + + /* compare this value to what we think should be the 'right' value */ + if (!trans->common_currency) + { + trans->common_currency = retval; + } + else if (!gnc_commodity_equiv (retval,trans->common_currency)) + { + PWARN ("expected common currency %s but found %s\n", + gnc_commodity_get_unique_name (trans->common_currency), + gnc_commodity_get_unique_name (retval)); + } + + return retval; } const gnc_commodity * @@ -1129,6 +1144,39 @@ xaccTransIsCommonExclSCurrency (Transaction *trans, return FindCommonExclSCurrency (trans->splits, ra, NULL, excl_split); } +/********************************************************************\ +\********************************************************************/ +/* The new routine for setting the common currency */ + +void +xaccTransSetCurrency (Transaction *trans, const gnc_commodity *curr) +{ + if (!trans || !curr) return; + + if (trans->common_currency) + { + PWARN ("currency already set\n"); + if (!gnc_commodity_equiv (curr,trans->common_currency)) + { + PWARN ("asked to change from common currency %s to %s\n" + "doing so hasn't been test and may orrupt the system\n", + gnc_commodity_get_unique_name (trans->common_currency), + gnc_commodity_get_unique_name (curr)); + } + } + else + { + trans->common_currency = curr; + + /* The following code will be obsolete when we finally eliminate + * the storage of the currency with the account. But in the meanwhile. + * we will try to keep it in sync, so that both the old and new ways + * work. + */ + + } +} + /********************************************************************\ \********************************************************************/ diff --git a/src/engine/Transaction.h b/src/engine/Transaction.h index b9e2c12115..cfbf2117c8 100644 --- a/src/engine/Transaction.h +++ b/src/engine/Transaction.h @@ -226,6 +226,33 @@ Timespec xaccTransRetDatePostedTS (Transaction *trans); */ int xaccTransCountSplits (Transaction *trans); +/* --------------------------------------------------------------- */ +/* Commmodities. Most of the commodty routines below are/will + * be obsolescent. They will all be replaced by two routines: + * xaccTransSet/GetCurrency(). + * The xaccTransGetCurrency() routine will give the same result + * as xaccTransFindCommonCurrency(), except that 'finding' won't + * be necessary: the common currency will be stored with the + * transaction. This will guarentee that a common currency is + * always avaiable, thus eliminating the need for many of the other + * checks and comparisons. + * + * Note side effect: the Account structure will no longer store + * a currency. Meanwhile, we'll be in a transition period, where + * we store teh currency both in the account and the transaction. + * Warning messages will print to the screen if things don't go well. + * If there are no warnings after a few months, then we'll make the + * transition permanent. Meanwhile, the xaccTransSetCurrency() + * will attempt to do 'the right thing'. + */ + +#define xaccTransGetCurrency xaccTransFindCommonCurrency +void xaccTransSetCurrency (Transaction *trans, + const gnc_commodity *curr); + +/* --------- + * and now for the 'old' routines + * --------- */ /* xaccIsCommonCurrency returns true if the given currency/security * pairs have a currency in common. It uses the same method as diff --git a/src/engine/TransactionP.h b/src/engine/TransactionP.h index a36a7578a3..308a4a0c23 100644 --- a/src/engine/TransactionP.h +++ b/src/engine/TransactionP.h @@ -153,6 +153,17 @@ struct _transaction * it's NULL until accessed. */ kvp_frame * kvp_data; + + /* The common_currency field indicates the currency type that + * all of the splits in this transaction share in common. This + * field is going to replace the currency field in the account + * structures. However, right now we are in a transition period: + * we store it here an in the account, and test its value dynamically + * for correctness. If we can run for a few months without errors, + * then we'll make the conversion permanent. + */ + const gnc_commodity *common_currency; + GList * splits; /* list of splits */ /* marker is used to track the progress of transaction traversals. diff --git a/src/engine/gnc-commodity.c b/src/engine/gnc-commodity.c index 8853efbf5d..229c3e4419 100644 --- a/src/engine/gnc-commodity.c +++ b/src/engine/gnc-commodity.c @@ -21,6 +21,7 @@ * * *******************************************************************/ +#define _GNU_SOURCE #include #include #include @@ -43,6 +44,7 @@ struct _gnc_commodity { char * printname; char * exchange_code; /* CUSIP or other identifying code */ int fraction; + char * unique_name; }; struct _gnc_commodity_namespace { @@ -78,6 +80,10 @@ gnc_commodity_new(const char * fullname, retval->mnemonic, retval->fullname); + retval->unique_name = g_strdup_printf("%s::%s", + retval->namespace, + retval->mnemonic); + return retval; } @@ -94,6 +100,7 @@ gnc_commodity_destroy(gnc_commodity * cm) { g_free(cm->namespace); g_free(cm->exchange_code); g_free(cm->mnemonic); + g_free(cm->unique_name); g_free(cm); } @@ -141,6 +148,16 @@ gnc_commodity_get_fullname(const gnc_commodity * cm) { } +/******************************************************************** + * gnc_commodity_get_unique_name + ********************************************************************/ + +const char * +gnc_commodity_get_unique_name(const gnc_commodity * cm) { + if(!cm) return NULL; + return cm->unique_name; +} + /******************************************************************** * gnc_commodity_get_exchange_code @@ -177,6 +194,10 @@ gnc_commodity_set_mnemonic(gnc_commodity * cm, const char * mnemonic) { g_free(cm->printname); cm->printname = g_strdup_printf("%s:%s (%s)", cm->namespace, cm->mnemonic, cm->fullname); + + g_free(cm->unique_name); + cm->unique_name = g_strdup_printf("%s::%s", + cm->namespace, cm->mnemonic); } /******************************************************************** @@ -186,8 +207,16 @@ gnc_commodity_set_mnemonic(gnc_commodity * cm, const char * mnemonic) { void gnc_commodity_set_namespace(gnc_commodity * cm, const char * namespace) { if(!cm) return; + g_free(cm->namespace); cm->namespace = g_strdup(namespace); + + g_free(cm->printname); + cm->printname = g_strdup_printf("%s:%s (%s)", + cm->namespace, cm->mnemonic, cm->fullname); + g_free(cm->unique_name); + cm->unique_name = g_strdup_printf("%s::%s", + cm->namespace, cm->mnemonic); } /******************************************************************** diff --git a/src/engine/gnc-commodity.h b/src/engine/gnc-commodity.h index b3ecfb9f66..2e556b146f 100644 --- a/src/engine/gnc-commodity.h +++ b/src/engine/gnc-commodity.h @@ -51,6 +51,7 @@ const char * gnc_commodity_get_namespace(const gnc_commodity * cm); const char * gnc_commodity_get_fullname(const gnc_commodity * cm); const char * gnc_commodity_get_printname(const gnc_commodity * cm); const char * gnc_commodity_get_exchange_code(const gnc_commodity * cm); +const char * gnc_commodity_get_unique_name(const gnc_commodity * cm); int gnc_commodity_get_fraction(const gnc_commodity * cm); void gnc_commodity_set_mnemonic(gnc_commodity * cm, const char * mnemonic);