Push gui independent functions into the engine.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@8146 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
David Hampton 2003-04-01 04:05:32 +00:00
parent 1c2adca030
commit f906f0b11b
5 changed files with 574 additions and 434 deletions

View File

@ -291,255 +291,165 @@ gnc_get_current_commodities (void)
return gnc_book_get_commodity_table (gnc_get_current_book ());
}
const char *
gnc_ui_account_get_field_name (AccountFieldCode field)
/*
* This is a wrapper routine around an xaccGetBalanceInCurrency
* function that handles additional needs of the gui.
*
* @param fn The underlying function in Account.c to call to retrieve
* a specific balance from the account.
* @param account The account to retrieve data about.
* @param recurse Include all sub-accounts of this account.
* @param negative An indication of whether or not the returned value
* is negative. This can be used by the caller to
* easily decode whether or not to color the output.
* @param commodity The commodity in which the account balance should
* be returned. If NULL, the value will be returned in
* the commodity of the account. This is normally used
* to specify a currency, which forces the conversion
* of things like stock account values from share
* values to an amount the requested currency.
*/
static gnc_numeric
gnc_ui_account_get_balance_internal (xaccGetBalanceInCurrencyFn fn,
Account *account,
gboolean recurse,
gboolean *negative,
gnc_commodity *commodity)
{
g_return_val_if_fail ((field >= 0) && (field < NUM_ACCOUNT_FIELDS), NULL);
gnc_numeric balance;
switch (field)
{
case ACCOUNT_TYPE :
return _("Type");
break;
case ACCOUNT_NAME :
return _("Account Name");
break;
case ACCOUNT_CODE :
return _("Account Code");
break;
case ACCOUNT_DESCRIPTION :
return _("Description");
break;
case ACCOUNT_NOTES :
return _("Notes");
break;
case ACCOUNT_COMMODITY :
return _("Commodity");
break;
case ACCOUNT_BALANCE :
return _("Balance");
break;
case ACCOUNT_BALANCE_REPORT :
return _("Balance");
break;
case ACCOUNT_TOTAL :
return _("Total");
break;
case ACCOUNT_TOTAL_REPORT :
return _("Total");
break;
case ACCOUNT_TAX_INFO :
return _("Tax Info");
default:
break;
}
balance = fn(account, commodity, recurse);
return NULL;
/* reverse sign if needed */
if (gnc_reverse_balance (account))
balance = gnc_numeric_neg (balance);
/* Record whether the balance is negative. */
if (negative)
*negative = gnc_numeric_negative_p(balance);
return balance;
}
/*
* This routine retrives the total balance in an account, possibly
* including all sub-accounts under the specified account.
*/
gnc_numeric
gnc_ui_account_get_balance (Account *account, gboolean recurse)
{
return gnc_ui_account_get_balance_internal (xaccAccountGetBalanceInCurrency,
account, recurse, NULL, NULL);
}
/*
* This routine retrives the reconciled balance in an account,
* possibly including all sub-accounts under the specified account.
*/
gnc_numeric
gnc_ui_account_get_reconciled_balance (Account *account,
gboolean recurse)
{
return gnc_ui_account_get_balance_internal (xaccAccountGetReconciledBalanceInCurrency,
account, recurse, NULL, NULL);
}
static gnc_numeric
gnc_account_get_balance_in_currency (Account *account,
gnc_commodity *currency)
/**
* Wrapper around gnc_ui_account_get_balance_internal that converts
* the resulting number to a character string. The number is
* formatted according to the specification of the account currency.
*
* @param fn The underlying function in Account.c to call to retrieve
* a specific balance from the account.
* @param account The account to retrieve data about.
* @param recurse Include all sub-accounts of this account.
* @param negative An indication of whether or not the returned value
* is negative. This can be used by the caller to
* easily decode whether or not to color the output.
*/
static gchar *
gnc_ui_account_get_print_balance (xaccGetBalanceInCurrencyFn fn,
Account *account,
gboolean recurse,
gboolean *negative)
{
GNCBook *book;
GNCPriceDB *pdb;
GNCPrice *price;
GNCPrintAmountInfo print_info;
gnc_numeric balance;
gnc_commodity *commodity;
if (!account || !currency)
return gnc_numeric_zero ();
balance = gnc_ui_account_get_balance_internal(fn, account, recurse,
negative, NULL);
print_info = gnc_account_print_info(account, TRUE);
return g_strdup(xaccPrintAmount(balance, print_info));
}
balance = xaccAccountGetBalance (account);
commodity = xaccAccountGetCommodity (account);
if (gnc_numeric_zero_p (balance) ||
gnc_commodity_equiv (currency, commodity))
return balance;
/**
* Wrapper around gnc_ui_account_get_balance_internal that converts
* the resulting number to a character string. The number is
* formatted according to the specification of the default reporting
* currency.
*
* @param fn The underlying function in Account.c to call to retrieve
* a specific balance from the account.
* @param account The account to retrieve data about.
* @param recurse Include all sub-accounts of this account.
* @param negative An indication of whether or not the returned value
* is negative. This can be used by the caller to
* easily decode whether or not to color the output.
*/
static gchar *
gnc_ui_account_get_print_report_balance (xaccGetBalanceInCurrencyFn fn,
Account *account,
gboolean recurse,
gboolean *negative)
{
GNCPrintAmountInfo print_info;
gnc_numeric balance;
gnc_commodity *report_commodity;
book = xaccGroupGetBook (xaccAccountGetRoot (account));
g_return_val_if_fail (book != NULL, gnc_numeric_zero ());
pdb = gnc_book_get_pricedb (book);
price = gnc_pricedb_lookup_latest (pdb, commodity, currency);
if (!price)
return gnc_numeric_zero ();
balance = gnc_numeric_mul (balance, gnc_price_get_value (price),
gnc_commodity_get_fraction (currency),
GNC_RND_ROUND);
gnc_price_unref (price);
return balance;
report_commodity = gnc_default_report_currency();
balance = gnc_ui_account_get_balance_internal(fn, account, recurse,
negative, report_commodity);
print_info = gnc_commodity_print_info(report_commodity, TRUE);
return g_strdup(xaccPrintAmount(balance, print_info));
}
gnc_numeric
gnc_ui_convert_balance_to_currency(gnc_numeric balance, gnc_commodity *balance_currency, gnc_commodity *currency)
{
GNCBook *book;
GNCPriceDB *pdb;
GNCPrice *price;
if (gnc_numeric_zero_p (balance) ||
gnc_commodity_equiv (currency, balance_currency))
return balance;
book = gnc_get_current_book ();
pdb = gnc_book_get_pricedb (book);
price = gnc_pricedb_lookup_latest (pdb, balance_currency, currency);
if (price)
{
balance = gnc_numeric_mul (balance, gnc_price_get_value (price),
gnc_commodity_get_fraction (currency),
GNC_RND_ROUND);
gnc_price_unref (price);
}
else
{
/* no direct price found, try if we find a price in another
currency and convert in two stages */
GList *price_list = gnc_pricedb_lookup_latest_any_currency(pdb, balance_currency);
if(price_list)
{
GList *list_helper = price_list;
gnc_numeric currency_price_value = gnc_numeric_zero();
gnc_commodity *intermediate_currency;
GNCPrice *currency_price;
do
{
price = (GNCPrice *)(list_helper->data);
intermediate_currency = gnc_price_get_currency(price);
currency_price = gnc_pricedb_lookup_latest(pdb, intermediate_currency, currency);
if(currency_price)
{
currency_price_value = gnc_price_get_value(currency_price);
gnc_price_unref(currency_price);
}
else
{
currency_price = gnc_pricedb_lookup_latest(pdb, currency, intermediate_currency);
if(currency_price)
{
/* here we need the reciprocal */
currency_price_value = gnc_numeric_div(gnc_numeric_create(1, 1),
gnc_price_get_value(currency_price),
gnc_commodity_get_fraction (currency),
GNC_RND_ROUND);
gnc_price_unref(currency_price);
}
}
list_helper = list_helper->next;
}
while((list_helper != NULL) && (!gnc_numeric_zero_p(currency_price_value)));
balance = gnc_numeric_mul (balance, currency_price_value,
gnc_commodity_get_fraction (currency),
GNC_RND_ROUND);
balance = gnc_numeric_mul (balance, gnc_price_get_value (price),
gnc_commodity_get_fraction (currency),
GNC_RND_ROUND);
gnc_price_list_destroy(price_list);
}
else
{
balance = gnc_numeric_zero ();
}
}
return balance;
}
static gnc_numeric
gnc_account_get_reconciled_balance_in_currency (Account *account,
gnc_commodity *currency)
gnc_ui_account_get_balance_as_of_date (Account *account, time_t date,
gboolean include_children)
{
gnc_numeric balance;
gnc_commodity *balance_currency;
if (!account || !currency)
return gnc_numeric_zero ();
balance = xaccAccountGetReconciledBalance (account);
balance_currency = xaccAccountGetCommodity (account);
return gnc_ui_convert_balance_to_currency (balance, balance_currency,
currency);
}
typedef struct
{
gnc_commodity *currency;
gnc_numeric balance;
} CurrencyBalance;
static gpointer
balance_helper (Account *account, gpointer data)
{
CurrencyBalance *cb = data;
gnc_numeric balance;
if (!cb->currency)
return NULL;
balance = gnc_account_get_balance_in_currency (account, cb->currency);
cb->balance = gnc_numeric_add (cb->balance, balance,
gnc_commodity_get_fraction (cb->currency),
GNC_RND_ROUND);
return NULL;
}
static gpointer
reconciled_balance_helper (Account *account, gpointer data)
{
CurrencyBalance *cb = data;
gnc_numeric balance;
balance = gnc_account_get_reconciled_balance_in_currency (account, cb->currency);
cb->balance = gnc_numeric_add (cb->balance, balance,
gnc_commodity_get_fraction (cb->currency),
GNC_RND_ROUND);
return NULL;
}
gnc_numeric
gnc_ui_account_get_balance (Account *account, gboolean include_children)
{
gnc_numeric balance;
gnc_commodity *commodity;
if (account == NULL)
return gnc_numeric_zero ();
commodity = xaccAccountGetCommodity (account);
balance = gnc_account_get_balance_in_currency (account, commodity);
currency = xaccAccountGetCommodity (account);
balance = xaccAccountGetBalanceAsOfDate (account, date);
if (include_children)
{
AccountGroup *children;
CurrencyBalance cb = { commodity, balance };
AccountGroup *children_group;
GList *children, *node;
children = xaccAccountGetChildren (account);
children_group = xaccAccountGetChildren (account);
children = xaccGroupGetSubAccounts (children_group);
xaccGroupForEachAccount (children, balance_helper, &cb, TRUE);
for (node = children; node; node = node->next)
{
Account *child;
gnc_commodity *child_currency;
gnc_numeric child_balance;
balance = cb.balance;
child = node->data;
child_currency = xaccAccountGetCommodity (child);
child_balance = xaccAccountGetBalanceAsOfDate (child, date);
child_balance = xaccAccountConvertBalanceToCurrency (child,
child_balance, child_currency, currency);
balance = gnc_numeric_add_fixed (balance, child_balance);
}
}
/* reverse sign if needed */
@ -549,7 +459,6 @@ gnc_ui_account_get_balance (Account *account, gboolean include_children)
return balance;
}
static char *
gnc_ui_account_get_tax_info_string (Account *account)
{
@ -631,88 +540,14 @@ gnc_ui_account_get_tax_info_string (Account *account)
}
gnc_numeric
gnc_ui_account_get_reconciled_balance (Account *account,
gboolean include_children)
{
gnc_numeric balance;
gnc_commodity *currency;
if (account == NULL)
return gnc_numeric_zero ();
currency = xaccAccountGetCommodity (account);
balance = gnc_account_get_reconciled_balance_in_currency (account, currency);
if (include_children)
{
AccountGroup *children;
CurrencyBalance cb = { currency, balance };
children = xaccAccountGetChildren (account);
xaccGroupForEachAccount (children, reconciled_balance_helper, &cb, TRUE);
balance = cb.balance;
}
/* reverse sign if needed */
if (gnc_reverse_balance (account))
balance = gnc_numeric_neg (balance);
return balance;
}
gnc_numeric
gnc_ui_account_get_balance_as_of_date (Account *account, time_t date,
gboolean include_children)
{
gnc_numeric balance;
gnc_commodity *currency;
if (account == NULL)
return gnc_numeric_zero ();
currency = xaccAccountGetCommodity (account);
balance = xaccAccountGetBalanceAsOfDate (account, date);
if (include_children)
{
AccountGroup *children_group;
GList *children, *node;
children_group = xaccAccountGetChildren (account);
children = xaccGroupGetSubAccounts (children_group);
for (node = children; node; node = node->next)
{
Account *child;
gnc_commodity *child_currency;
gnc_numeric child_balance;
child = node->data;
child_currency = xaccAccountGetCommodity (child);
child_balance = xaccAccountGetBalanceAsOfDate (child, date);
child_balance = gnc_ui_convert_balance_to_currency
(child_balance, child_currency, currency);
balance = gnc_numeric_add_fixed (balance, child_balance);
}
}
/* reverse sign if needed */
if (gnc_reverse_balance (account))
balance = gnc_numeric_neg (balance);
return balance;
}
char *
gnc_ui_account_get_field_value_string (Account *account,
AccountFieldCode field)
AccountFieldCode field,
gboolean *negative)
{
g_return_val_if_fail ((field >= 0) && (field < NUM_ACCOUNT_FIELDS), NULL);
*negative = FALSE;
if (account == NULL)
return NULL;
@ -738,49 +573,66 @@ gnc_ui_account_get_field_value_string (Account *account,
g_strdup
(gnc_commodity_get_printname(xaccAccountGetCommodity(account)));
case ACCOUNT_BALANCE :
{
gnc_numeric balance = gnc_ui_account_get_balance(account, FALSE);
case ACCOUNT_PRESENT :
return
gnc_ui_account_get_print_balance(xaccAccountGetPresentBalanceInCurrency,
account, FALSE, negative);
return g_strdup
(xaccPrintAmount (balance, gnc_account_print_info (account, TRUE)));
}
case ACCOUNT_PRESENT_REPORT :
return
gnc_ui_account_get_print_report_balance(xaccAccountGetPresentBalanceInCurrency,
account, FALSE, negative);
case ACCOUNT_BALANCE :
return
gnc_ui_account_get_print_balance(xaccAccountGetBalanceInCurrency,
account, FALSE, negative);
case ACCOUNT_BALANCE_REPORT :
{
gnc_commodity * commodity = xaccAccountGetCommodity(account);
gnc_commodity * report_commodity = gnc_default_report_currency();
gnc_numeric balance = gnc_ui_account_get_balance(account, FALSE);
return
gnc_ui_account_get_print_report_balance(xaccAccountGetBalanceInCurrency,
account, FALSE, negative);
gnc_numeric report_balance = gnc_ui_convert_balance_to_currency(balance, commodity,
report_commodity);
case ACCOUNT_CLEARED :
return
gnc_ui_account_get_print_balance(xaccAccountGetClearedBalanceInCurrency,
account, FALSE, negative);
return g_strdup
(xaccPrintAmount(report_balance,
gnc_commodity_print_info (report_commodity, TRUE)));
}
case ACCOUNT_CLEARED_REPORT :
return
gnc_ui_account_get_print_report_balance(xaccAccountGetClearedBalanceInCurrency,
account, FALSE, negative);
case ACCOUNT_RECONCILED :
return
gnc_ui_account_get_print_balance(xaccAccountGetReconciledBalanceInCurrency,
account, FALSE, negative);
case ACCOUNT_RECONCILED_REPORT :
return
gnc_ui_account_get_print_report_balance(xaccAccountGetReconciledBalanceInCurrency,
account, FALSE, negative);
case ACCOUNT_FUTURE_MIN :
return
gnc_ui_account_get_print_balance(xaccAccountGetProjectedMinimumBalanceInCurrency,
account, FALSE, negative);
case ACCOUNT_FUTURE_MIN_REPORT :
return
gnc_ui_account_get_print_report_balance(xaccAccountGetProjectedMinimumBalanceInCurrency,
account, FALSE, negative);
case ACCOUNT_TOTAL :
{
gnc_numeric balance = gnc_ui_account_get_balance(account, TRUE);
return
gnc_ui_account_get_print_balance(xaccAccountGetBalanceInCurrency,
account, TRUE, negative);
return g_strdup
(xaccPrintAmount(balance, gnc_account_print_info (account, TRUE)));
}
case ACCOUNT_TOTAL_REPORT :
{
gnc_commodity * commodity = xaccAccountGetCommodity(account);
gnc_commodity * report_commodity = gnc_default_report_currency();
gnc_numeric balance = gnc_ui_account_get_balance(account, TRUE);
gnc_numeric report_balance = gnc_ui_convert_balance_to_currency(balance, commodity,
report_commodity);
return g_strdup
(xaccPrintAmount(report_balance,
gnc_commodity_print_info (report_commodity, TRUE)));
}
return
gnc_ui_account_get_print_report_balance(xaccAccountGetBalanceInCurrency,
account, TRUE, negative);
case ACCOUNT_TAX_INFO:
return gnc_ui_account_get_tax_info_string (account);

View File

@ -20,6 +20,13 @@
* Boston, MA 02111-1307, USA gnu@gnu.org *
\********************************************************************/
/** @addtogroup UI
@{ */
/** @file gnc-ui-util.h
@brief utility functions for the GnuCash UI
@author Copyright (C) 2000 Dave Peticolas <dave@krondo.com>
*/
#ifndef GNC_UI_UTIL_H
#define GNC_UI_UTIL_H
@ -57,37 +64,75 @@ GNCBook * gnc_get_current_book (void);
AccountGroup * gnc_get_current_group (void);
gnc_commodity_table * gnc_get_current_commodities (void);
/*
* These values are order according to the way they should appear in
* the register. If you change this enum, you must also change the
* acct_tree_defaults data structure in gnc-account-tree.c.
*/
typedef enum
{
ACCOUNT_TYPE = 0,
ACCOUNT_NAME,
ACCOUNT_NAME = 0,
ACCOUNT_TYPE,
ACCOUNT_COMMODITY,
ACCOUNT_CODE,
ACCOUNT_DESCRIPTION,
ACCOUNT_NOTES,
ACCOUNT_COMMODITY,
ACCOUNT_PRESENT,
ACCOUNT_PRESENT_REPORT,
ACCOUNT_BALANCE, /* with sign reversal */
ACCOUNT_BALANCE_REPORT, /* ACCOUNT_BALANCE in default report currency */
ACCOUNT_CLEARED,
ACCOUNT_CLEARED_REPORT,
ACCOUNT_RECONCILED,
ACCOUNT_RECONCILED_REPORT,
ACCOUNT_FUTURE_MIN,
ACCOUNT_FUTURE_MIN_REPORT,
ACCOUNT_TOTAL, /* balance + children's balance with sign reversal */
ACCOUNT_TOTAL_REPORT, /* ACCOUNT_TOTAL in default report currency */
ACCOUNT_NOTES,
ACCOUNT_TAX_INFO,
NUM_ACCOUNT_FIELDS
} AccountFieldCode;
const char * gnc_ui_account_get_field_name (AccountFieldCode field);
/* Must g_free string when done */
/**
* This routine retrives the content for any given field in the
* account tree data structure. The account specifies the "row" and
* the field parameter specifies the "column". In essence, this is
* one giant accessor routine for the Account object where all the
* results are string values.
*
* @param account The account to retrieve data about.
* @param field An indicator of which field in the account tree to return
* @param negative An indicator that the result was a negative numeric
* value. May be used by the caller for colorization of the
* returned string.
* @return The textual string representing the requested field.
*
* @note The caller must free the returned string when done with it.
*/
char * gnc_ui_account_get_field_value_string (Account *account,
AccountFieldCode field);
gnc_numeric gnc_ui_convert_balance_to_currency(gnc_numeric balance,
gnc_commodity *balance_currency,
gnc_commodity *currency);
AccountFieldCode field,
gboolean *negative);
/**
* This routine retrives the total balance in an account, possibly
* including all sub-accounts under the specified account.
*
* @param account The account to retrieve data about.
* @param include_children Include all sub-accounts of this account.
*/
gnc_numeric gnc_ui_account_get_balance (Account *account,
gboolean include_children);
/**
* This routine retrives the reconciled balance in an account,
* possibly including all sub-accounts under the specified account.
*
* @param account The account to retrieve data about.
* @param include_children Include all sub-accounts of this account.
*/
gnc_numeric gnc_ui_account_get_reconciled_balance(Account *account,
gboolean include_children);
gnc_numeric gnc_ui_account_get_balance_as_of_date (Account *account,
time_t date,
gboolean include_children);
@ -281,3 +326,4 @@ int iswlower (gint32 wc);
#endif
#endif
/** @} */

View File

@ -1182,7 +1182,7 @@ xaccAccountRecomputeBalance (Account * acc)
balance = gnc_numeric_add_fixed(balance, split->amount);
if (NREC != split->reconciled)
if (CREC == split->reconciled)
cleared_balance = gnc_numeric_add_fixed(cleared_balance, split->amount);
if (YREC == split->reconciled ||
@ -1855,6 +1855,38 @@ xaccAccountGetReconciledBalance (Account *acc)
return acc->reconciled_balance;
}
gnc_numeric
xaccAccountGetProjectedMinimumBalance (Account *account)
{
GList *node;
time_t today;
gnc_numeric lowest = gnc_numeric_zero ();
int seen_a_transaction = 0;
if (!account)
return gnc_numeric_zero ();
today = gnc_timet_get_today_end();
for (node = g_list_last (account->splits); node; node = node->prev)
{
Split *split = node->data;
if (!seen_a_transaction)
{
lowest = xaccSplitGetBalance (split);
seen_a_transaction = 1;
} else if (gnc_numeric_compare(xaccSplitGetBalance (split), lowest) < 0) {
lowest = xaccSplitGetBalance (split);
}
if (xaccTransGetDate (xaccSplitGetParent (split)) <= today)
return lowest;
}
return lowest;
}
/********************************************************************\
\********************************************************************/
@ -1912,6 +1944,258 @@ xaccAccountGetBalanceAsOfDate (Account *acc, time_t date)
return( balance );
}
/*
* Originally gsr_account_present_balance in gnc-split-reg.c
*
* How does this routine compare to xaccAccountGetBalanceAsOfDate just
* above? These two routines should eventually be collapsed into one.
* Perhaps the startup logic from that one, and the logic from this
* one that walks from the tail of the split list.
*/
gnc_numeric
xaccAccountGetPresentBalance (Account *account)
{
GList *node;
time_t today;
if (!account)
return gnc_numeric_zero ();
today = gnc_timet_get_today_end();
for (node = g_list_last (account->splits); node; node = node->prev)
{
Split *split = node->data;
if (xaccTransGetDate (xaccSplitGetParent (split)) <= today)
return xaccSplitGetBalance (split);
}
return gnc_numeric_zero ();
}
/********************************************************************\
\********************************************************************/
/*
* Convert a balance from one currency to another.
*/
gnc_numeric
xaccAccountConvertBalanceToCurrency(Account *account, /* for book */
gnc_numeric balance,
gnc_commodity *balance_currency,
gnc_commodity *new_currency)
{
GNCBook *book;
GNCPriceDB *pdb;
GNCPrice *price, *currency_price;
GList *price_list, *list_helper;
gnc_numeric currency_price_value;
gnc_commodity *intermediate_currency;
if (gnc_numeric_zero_p (balance) ||
gnc_commodity_equiv (balance_currency, new_currency))
return balance;
book = xaccGroupGetBook (xaccAccountGetRoot (account));
pdb = gnc_book_get_pricedb (book);
/* Look for a direct price. */
price = gnc_pricedb_lookup_latest (pdb, balance_currency, new_currency);
if (price) {
balance = gnc_numeric_mul (balance, gnc_price_get_value (price),
gnc_commodity_get_fraction (new_currency),
GNC_RND_ROUND);
gnc_price_unref (price);
return balance;
}
/*
* no direct price found, try if we find a price in another currency
* and convert in two stages
*/
price_list = gnc_pricedb_lookup_latest_any_currency(pdb, balance_currency);
if (!price_list) {
balance = gnc_numeric_zero ();
return balance;
}
list_helper = price_list;
currency_price_value = gnc_numeric_zero();
do {
price = (GNCPrice *)(list_helper->data);
intermediate_currency = gnc_price_get_currency(price);
currency_price = gnc_pricedb_lookup_latest(pdb, intermediate_currency,
new_currency);
if(currency_price) {
currency_price_value = gnc_price_get_value(currency_price);
gnc_price_unref(currency_price);
} else {
currency_price = gnc_pricedb_lookup_latest(pdb, new_currency,
intermediate_currency);
if (currency_price) {
/* here we need the reciprocal */
currency_price_value = gnc_numeric_div(gnc_numeric_create(1, 1),
gnc_price_get_value(currency_price),
gnc_commodity_get_fraction (new_currency),
GNC_RND_ROUND);
gnc_price_unref(currency_price);
}
}
list_helper = list_helper->next;
} while((list_helper != NULL) &&
(!gnc_numeric_zero_p(currency_price_value)));
balance = gnc_numeric_mul (balance, currency_price_value,
gnc_commodity_get_fraction (new_currency),
GNC_RND_ROUND);
balance = gnc_numeric_mul (balance, gnc_price_get_value (price),
gnc_commodity_get_fraction (new_currency),
GNC_RND_ROUND);
gnc_price_list_destroy(price_list);
return balance;
}
/*
* Given an account and a GetBalanceFn pointer, extract the requested
* balance from the account and then convert it to the desired
* currency.
*/
static gnc_numeric
xaccAccountGetXxxBalanceInCurrency (Account *account,
xaccGetBalanceFn fn,
gnc_commodity *report_currency)
{
gnc_numeric balance;
if (!account || !fn || !report_currency)
return gnc_numeric_zero ();
balance = fn(account);
return xaccAccountConvertBalanceToCurrency(account, balance,
account->commodity,
report_currency);
}
/*
* Data structure used to pass various arguments into the following fn.
*/
typedef struct
{
gnc_commodity *currency;
gnc_numeric balance;
xaccGetBalanceFn fn;
} CurrencyBalance;
/*
* A helper function for iterating over all the accounts in a list or
* tree. This function is called once per account, and sums up the
* values of all these accounts.
*/
static gpointer
xaccAccountBalanceHelper (Account *account, gpointer data)
{
CurrencyBalance *cb = data;
gnc_numeric balance;
if (!cb->fn || !cb->currency)
return NULL;
balance = xaccAccountGetXxxBalanceInCurrency (account, cb->fn, cb->currency);
cb->balance = gnc_numeric_add (cb->balance, balance,
gnc_commodity_get_fraction (cb->currency),
GNC_RND_ROUND);
return NULL;
}
/*
* Common function that iterates recursively over all accounts below
* the specified account. It uses the previous routine to sum up the
* balances of all its children, and uses the specified function for
* extracting the balance. This function may extract the current
* value, the reconciled value, etc.
*/
static gnc_numeric
xaccAccountGetXxxBalanceInCurrencyRecursive (Account *account,
xaccGetBalanceFn fn,
gnc_commodity *report_commodity,
gboolean include_children)
{
gnc_numeric balance;
if (account == NULL)
return gnc_numeric_zero ();
if (!report_commodity)
report_commodity = xaccAccountGetCommodity (account);
balance = xaccAccountGetXxxBalanceInCurrency (account, fn, report_commodity);
/* If needed, sum up the children converting to *this* account's commodity. */
if (include_children)
{
CurrencyBalance cb = { report_commodity, balance, fn };
xaccGroupForEachAccount (account->children, xaccAccountBalanceHelper, &cb, TRUE);
balance = cb.balance;
}
return balance;
}
gnc_numeric
xaccAccountGetBalanceInCurrency (Account *account,
gnc_commodity *report_commodity,
gboolean include_children)
{
return
xaccAccountGetXxxBalanceInCurrencyRecursive (account, xaccAccountGetBalance,
report_commodity, include_children);
}
gnc_numeric
xaccAccountGetClearedBalanceInCurrency (Account *account,
gnc_commodity *report_commodity,
gboolean include_children)
{
return
xaccAccountGetXxxBalanceInCurrencyRecursive (account, xaccAccountGetClearedBalance,
report_commodity, include_children);
}
gnc_numeric
xaccAccountGetReconciledBalanceInCurrency (Account *account,
gnc_commodity *report_commodity,
gboolean include_children)
{
return
xaccAccountGetXxxBalanceInCurrencyRecursive (account, xaccAccountGetReconciledBalance,
report_commodity, include_children);
}
gnc_numeric
xaccAccountGetPresentBalanceInCurrency (Account *account,
gnc_commodity *report_commodity,
gboolean include_children)
{
return
xaccAccountGetXxxBalanceInCurrencyRecursive (account, xaccAccountGetPresentBalance,
report_commodity, include_children);
}
gnc_numeric
xaccAccountGetProjectedMinimumBalanceInCurrency (Account *account,
gnc_commodity *report_commodity,
gboolean include_children)
{
return
xaccAccountGetXxxBalanceInCurrencyRecursive (account, xaccAccountGetProjectedMinimumBalance,
report_commodity, include_children);
}
/********************************************************************\
\********************************************************************/
@ -2950,9 +3234,11 @@ gboolean xaccAccountRegister (void)
{ ACCOUNT_CODE_, QUERYCORE_STRING, (QueryAccess)xaccAccountGetCode },
{ ACCOUNT_DESCRIPTION_, QUERYCORE_STRING, (QueryAccess)xaccAccountGetDescription },
{ ACCOUNT_NOTES_, QUERYCORE_STRING, (QueryAccess)xaccAccountGetNotes },
{ ACCOUNT_PRESENT_, QUERYCORE_NUMERIC, (QueryAccess)xaccAccountGetPresentBalance },
{ ACCOUNT_BALANCE_, QUERYCORE_NUMERIC, (QueryAccess)xaccAccountGetBalance },
{ ACCOUNT_CLEARED_BALANCE, QUERYCORE_NUMERIC, (QueryAccess)xaccAccountGetClearedBalance },
{ ACCOUNT_RECONCILED_BALANCE, QUERYCORE_NUMERIC, (QueryAccess)xaccAccountGetReconciledBalance },
{ ACCOUNT_CLEARED_, QUERYCORE_NUMERIC, (QueryAccess)xaccAccountGetClearedBalance },
{ ACCOUNT_RECONCILED_, QUERYCORE_NUMERIC, (QueryAccess)xaccAccountGetReconciledBalance },
{ ACCOUNT_FUTURE_MINIMUM_, QUERYCORE_NUMERIC, (QueryAccess)xaccAccountGetProjectedMinimumBalance },
{ ACCOUNT_TAX_RELATED, QUERYCORE_BOOLEAN, (QueryAccess)xaccAccountGetTaxRelated },
{ QUERY_PARAM_BOOK, GNC_ID_BOOK, (QueryAccess)xaccAccountGetBook },
{ QUERY_PARAM_GUID, QUERYCORE_GUID, (QueryAccess)xaccAccountGetGUID },

View File

@ -34,6 +34,10 @@
#include "kvp_frame.h"
typedef gnc_numeric (*xaccGetBalanceFn)( Account *account );
typedef gnc_numeric (*xaccGetBalanceInCurrencyFn) (Account *account,
gnc_commodity *report_commodity,
gboolean include_children);
/** The account types are used to determine how the transaction data
* in the account is displayed. These values can be safely changed
@ -311,8 +315,30 @@ gnc_numeric xaccAccountGetBalance (Account *account);
gnc_numeric xaccAccountGetClearedBalance (Account *account);
/** Get the current balance of the account, only including reconciled transactions */
gnc_numeric xaccAccountGetReconciledBalance (Account *account);
gnc_numeric xaccAccountGetPresentBalance (Account *account);
gnc_numeric xaccAccountGetProjectedMinimumBalance (Account *account);
/** Get the balance of the account as of the date specified */
gnc_numeric xaccAccountGetBalanceAsOfDate (Account *account, time_t date);
gnc_numeric xaccAccountConvertBalanceToCurrency(Account *account, /* for book */
gnc_numeric balance,
gnc_commodity *balance_currency,
gnc_commodity *new_currency);
gnc_numeric xaccAccountGetBalanceInCurrency (Account *account,
gnc_commodity *report_commodity,
gboolean include_children);
gnc_numeric xaccAccountGetClearedBalanceInCurrency (Account *account,
gnc_commodity *report_commodity,
gboolean include_children);
gnc_numeric xaccAccountGetReconciledBalanceInCurrency (Account *account,
gnc_commodity *report_commodity,
gboolean include_children);
gnc_numeric xaccAccountGetPresentBalanceInCurrency (Account *account,
gnc_commodity *report_commodity,
gboolean include_children);
gnc_numeric xaccAccountGetProjectedMinimumBalanceInCurrency (Account *account,
gnc_commodity *report_commodity,
gboolean include_children);
/*@}*/
@ -689,8 +715,10 @@ const char * xaccAccountGetQuoteTZ (Account *account);
#define ACCOUNT_DESCRIPTION_ "desc"
#define ACCOUNT_NOTES_ "notes"
#define ACCOUNT_BALANCE_ "balance"
#define ACCOUNT_CLEARED_BALANCE "cleared-balance"
#define ACCOUNT_RECONCILED_BALANCE "reconciled-balance"
#define ACCOUNT_CLEARED_ "cleared"
#define ACCOUNT_RECONCILED_ "reconciled"
#define ACCOUNT_PRESENT_ "present"
#define ACCOUNT_FUTURE_MINIMUM_ "future-minimum"
#define ACCOUNT_TAX_RELATED "tax-related-p"
/** @} */

View File

@ -92,8 +92,6 @@ static void gnc_split_reg_determine_read_only( GNCSplitReg *gsr );
static void gnc_split_reg_change_style (GNCSplitReg *gsr, SplitRegisterStyle style);
static GNCPlaceholderType gnc_split_reg_get_placeholder( GNCSplitReg *gsr );
static gnc_numeric gsr_account_present_balance( Account *account );
static gnc_numeric gsr_account_projectedminimum_balance( Account *account );
static gncUIWidget gnc_split_reg_get_parent( GNCLedgerDisplay *ledger );
static void gsr_create_menus( GNCSplitReg *gsr );
@ -106,13 +104,8 @@ static void gsr_setup_status_widgets( GNCSplitReg *gsr );
static GtkWidget* gsr_create_popup_menu( GNCSplitReg *gsr );
/**
* Defines a function pointer def to get a gnc_numeric from an account.
**/
typedef gnc_numeric (*AmountGetterFn)(Account*);
static void gsr_update_summary_label( GtkWidget *label,
AmountGetterFn getter,
xaccGetBalanceFn getter,
Account *leader,
GNCPrintAmountInfo print_info,
gnc_commodity *cmdty,
@ -596,7 +589,7 @@ gnc_split_reg_raise( GNCSplitReg *gsr )
static
void
gsr_update_summary_label( GtkWidget *label,
AmountGetterFn getter,
xaccGetBalanceFn getter,
Account *leader,
GNCPrintAmountInfo print_info,
gnc_commodity *cmdty,
@ -703,19 +696,19 @@ gsr_redraw_all_cb (GnucashRegister *g_reg, gpointer data)
if ( gsr->createFlags & CREATE_SUMMARYBAR ) {
gsr_update_summary_label( gsr->balance_label,
(AmountGetterFn)gsr_account_present_balance,
xaccAccountGetPresentBalance,
leader, print_info, commodity, reverse, euro );
gsr_update_summary_label( gsr->cleared_label,
(AmountGetterFn)xaccAccountGetClearedBalance,
xaccAccountGetClearedBalance,
leader, print_info, commodity, reverse, euro );
gsr_update_summary_label( gsr->reconciled_label,
(AmountGetterFn)xaccAccountGetReconciledBalance,
xaccAccountGetReconciledBalance,
leader, print_info, commodity, reverse, euro );
gsr_update_summary_label( gsr->future_label,
(AmountGetterFn)xaccAccountGetBalance,
xaccAccountGetBalance,
leader, print_info, commodity, reverse, euro );
gsr_update_summary_label( gsr->projectedminimum_label,
(AmountGetterFn)gsr_account_projectedminimum_balance,
xaccAccountGetProjectedMinimumBalance,
leader, print_info, commodity, reverse, euro );
if (gsr->shares_label != NULL)
@ -759,12 +752,15 @@ gsr_redraw_all_cb (GnucashRegister *g_reg, gpointer data)
if (reverse)
amount = gnc_numeric_neg (amount);
currency_amount = gnc_ui_convert_balance_to_currency(amount, commodity, currency);
currency_amount =
xaccAccountConvertBalanceToCurrency(leader, amount,
commodity, currency);
xaccSPrintAmount (string, currency_amount, print_info);
default_currency_amount = gnc_ui_convert_balance_to_currency(amount, commodity,
default_currency);
default_currency_amount =
xaccAccountConvertBalanceToCurrency(leader, amount,
commodity,
default_currency);
if(!gnc_numeric_zero_p(default_currency_amount))
{
strcat( string, " / " );
@ -2124,74 +2120,6 @@ gnc_toolbar_change_cb (void *data)
gnc_split_reg_refresh_toolbar( gsr );
}
/**
* A utility function which retreives the present balance from an Account.
* This should move somewhere more general?
**/
static
gnc_numeric
gsr_account_present_balance (Account *account)
{
GList *list;
GList *node;
time_t today;
if (!account)
return gnc_numeric_zero ();
today = gnc_timet_get_today_end();
list = xaccAccountGetSplitList (account);
for (node = g_list_last (list); node; node = node->prev)
{
Split *split = node->data;
if (xaccTransGetDate (xaccSplitGetParent (split)) <= today)
return xaccSplitGetBalance (split);
}
return gnc_numeric_zero ();
}
/**
* A utility function which retreives the present balance from an Account.
* This should move somewhere more general?
**/
static
gnc_numeric
gsr_account_projectedminimum_balance (Account *account)
{
GList *list;
GList *node;
time_t today;
gnc_numeric lowest = gnc_numeric_zero ();
int seen_a_transaction = 0;
if (!account)
return gnc_numeric_zero ();
today = gnc_timet_get_today_end();
list = xaccAccountGetSplitList (account);
for (node = g_list_last (list); node; node = node->prev)
{
Split *split = node->data;
if (!seen_a_transaction)
{
lowest = xaccSplitGetBalance (split);
seen_a_transaction = 1;
}
if ( gnc_numeric_compare(xaccSplitGetBalance (split), lowest) < 0 )
lowest = xaccSplitGetBalance (split);
if (xaccTransGetDate (xaccSplitGetParent (split)) <= today)
return lowest;
}
return lowest;
}
static
gncUIWidget
gnc_split_reg_get_parent( GNCLedgerDisplay *ledger )