Paul Campbell's code to allow child accounts to be reconciled

with the parent.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@5412 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Dave Peticolas 2001-09-23 04:29:15 +00:00
parent a85fb2a89b
commit 277796dfad
10 changed files with 330 additions and 5 deletions

View File

@ -84,6 +84,7 @@ Terry Boldt <tboldt@attglobal.net> financial calculator and expression parser
Richard Braakman <dark@xs4all.nl) xml version configure patch
Simon Britnell <simon.britnell@peace.com> patch to RPM spec
Christopher B. Browne <cbbrowne@hex.net> for perl, lots of scheme and documentation updates
Paul Campbell <kemitix@users.sourceforge.net> reconcile children patch
Conrad Canterford <conrad@mail.watersprite.com.au> register bug fix
Bill Carlson <wwc@wwcnet.nu> performance improvements
David Mar?n Carre?o <davefx@aspl.f2s.com> Spanish translation of account setup.

View File

@ -267,6 +267,14 @@ linkend="scheme"> Scheme </link>, the <link linkend="gwrap"> g-wrap
</glossdef>
</glossentry>
<glossentry>
<glossterm><email>kemitix@users.sourceforge.net</email> Paul
Campbell</glossterm>
<glossdef>
<para>reconcile children patch</para>
</glossdef>
</glossentry>
<glossentry>
<glossterm><email>conrad@mail.watersprite.com.au</email> Conrad
Canterford</glossterm>

View File

@ -311,6 +311,54 @@ gnc_account_get_balance_in_currency (Account *account,
}
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)
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;
}
static gnc_numeric
gnc_account_get_reconciled_balance_in_currency (Account *account,
gnc_commodity *currency)
{
GNCBook *book;
GNCPriceDB *pdb;
GNCPrice *price;
gboolean has_shares;
gnc_numeric balance;
GNCAccountType atype;
gnc_commodity *balance_currency;
if (!account || !currency)
return gnc_numeric_zero ();
balance = xaccAccountGetReconciledBalance (account);
balance_currency = DxaccAccountGetCurrency (account);
return gnc_ui_convert_balance_to_currency (balance, balance_currency, currency);
}
typedef struct
{
gnc_commodity *currency;
@ -336,6 +384,21 @@ balance_helper (Account *account, gpointer data)
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)
{
@ -450,6 +513,82 @@ 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 = DxaccAccountGetCurrency (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 = DxaccAccountGetCurrency (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 = (Account *)node->data;
child_currency = DxaccAccountGetCurrency (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)

View File

@ -73,9 +73,16 @@ const char * gnc_ui_account_get_field_name (AccountFieldCode field);
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);
gnc_numeric gnc_ui_account_get_balance (Account *account,
gboolean include_children);
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);
const char * gnc_get_reconcile_str (char reconciled_flag);
typedef enum

View File

@ -2054,6 +2054,48 @@ xaccAccountGetQuoteTZ(Account *acc)
return NULL;
}
/********************************************************************\
\********************************************************************/
void
xaccAccountSetReconcileChildrenStatus(Account *account, gboolean status)
{
kvp_frame *frame;
if (!account)
return;
xaccAccountBeginEdit (account);
frame = kvp_frame_get_frame (account->kvp_data, "reconcile-info", NULL);
kvp_frame_set_slot_nc (frame,
"include-children",
status ? kvp_value_new_gint64 (status) : NULL);
account->core_dirty = TRUE;
xaccAccountCommitEdit (account);
return;
}
/********************************************************************\
\********************************************************************/
gboolean
xaccAccountGetReconcileChildrenStatus(Account *account)
{
kvp_value *status;
if (!account)
return FALSE;
/* access the account's kvp-data for status and return that, if no value
* is found then we can assume not to include the children, that being
* the default behaviour
*/
status = kvp_frame_get_slot_path (account->kvp_data,
"reconcile-info",
"include-children",
NULL);
if (!status)
return FALSE;
return kvp_value_get_gint64 (status);
}
/********************************************************************\
\********************************************************************/

View File

@ -234,6 +234,9 @@ gnc_numeric xaccAccountGetBalance (Account *account);
gnc_numeric xaccAccountGetClearedBalance (Account *account);
gnc_numeric xaccAccountGetReconciledBalance (Account *account);
void xaccAccountSetReconcileChildrenStatus(Account *account, gboolean status);
gboolean xaccAccountGetReconcileChildrenStatus(Account *account);
gnc_numeric xaccAccountGetBalanceAsOfDate (Account *account, time_t date);
GList* xaccAccountGetSplitList (Account *account);

View File

@ -102,6 +102,12 @@ Type: frame
Entities: Account
Use: store reconcile information about accounts
Name: reconcile-info/include-children
Type: gint64
Entities: Account
Use: A boolean flag indicating whether transactions in sub-accounts should be
included during reconcilition.
Name: reconcile-info/last-date
Type: frame
Entities: Account

View File

@ -98,6 +98,7 @@ GtkWidget *
gnc_reconcile_list_new(Account *account, GNCReconcileListType type)
{
GNCReconcileList *list;
gboolean include_children;
g_assert(account != NULL);
g_assert((type == RECLIST_DEBIT) || (type == RECLIST_CREDIT));
@ -114,6 +115,20 @@ gnc_reconcile_list_new(Account *account, GNCReconcileListType type)
/* match the account */
xaccQueryAddSingleAccountMatch(list->query, account, QUERY_OR);
include_children = xaccAccountGetReconcileChildrenStatus(account);
if(include_children)
{
/* match child accounts */
AccountGroup *account_group = xaccAccountGetChildren(account);
GList *children_list = xaccGroupGetSubAccounts(account_group);
GList *node;
for (node = children_list; node; node = node->next)
xaccQueryAddSingleAccountMatch (list->query, node->data, QUERY_OR);
g_list_free (children_list);
}
if (type == RECLIST_CREDIT)
DxaccQueryAddAmountMatch(list->query, 0.0, AMT_SGN_MATCH_CREDIT,
AMT_MATCH_ATLEAST, QUERY_AND);
@ -241,11 +256,87 @@ gnc_reconcile_list_class_init (GNCReconcileListClass *klass)
klass->double_click_split = NULL;
}
static void
gnc_reconcile_list_toggle_row(GNCReconcileList *list, gint row)
{
Split *split, *current;
g_assert (IS_GNC_RECONCILE_LIST(list));
g_assert (list->reconciled != NULL);
if (list->no_toggle)
return;
split = gtk_clist_get_row_data (GTK_CLIST(list), row);
current = g_hash_table_lookup (list->reconciled, split);
list->current_split = split;
if (current == NULL)
g_hash_table_insert (list->reconciled, split, split);
else
g_hash_table_remove (list->reconciled, split);
update_toggle (GTK_CLIST (list), row);
}
static void
gnc_reconcile_list_toggle_children(Account *account, GNCReconcileList *list, Split *split)
{
AccountGroup *account_group;
GList *child_accounts, *node;
Transaction *transaction;
/*
* Need to get all splits in this transaction and identify any that are
* in the same heirarchy as the account being reconciled (not necessarily
* the account this split is from.)
*
* For each of these splits toggle them all to the same state.
*/
account_group = xaccAccountGetChildren(account);
child_accounts = xaccGroupGetSubAccounts(account_group);
child_accounts = g_list_prepend(child_accounts, account);
transaction = xaccSplitGetParent(split);
for(node = xaccTransGetSplitList(transaction); node; node = node->next)
{
Split *other_split;
Account *other_account;
GNCReconcileList *current_list;
gint row;
GtkCList *split_list;
other_split = node->data;
other_account = xaccSplitGetAccount(other_split);
if(other_split == split)
continue;
/* Check this 'other' account in in the same heirarchy */
if(!g_list_find(child_accounts,other_account))
continue;
/* Search our sibling list for this split first. We search the
* sibling list first because that it where it is most likely to be.
*/
current_list = list->sibling;
row = gtk_clist_find_row_from_data(GTK_CLIST(&current_list->clist), other_split);
if(row == -1) {
/* Not in the sibling list, try this list */
current_list = list;
row = gtk_clist_find_row_from_data(GTK_CLIST(&current_list->clist), other_split);
if(row == -1)
/* We can't find it, nothing more I can do about it */
continue;
}
gnc_reconcile_list_toggle_row(current_list, row);
}
}
static void
gnc_reconcile_list_toggle (GNCReconcileList *list)
{
Split *split, *current;
gint row;
Account * account;
gboolean include_children;
g_assert (IS_GNC_RECONCILE_LIST(list));
g_assert (list->reconciled != NULL);
@ -266,6 +357,10 @@ gnc_reconcile_list_toggle (GNCReconcileList *list)
update_toggle (GTK_CLIST (list), row);
include_children = xaccAccountGetReconcileChildrenStatus(list->account);
if(include_children)
gnc_reconcile_list_toggle_children(list->account, list, split);
gtk_signal_emit (GTK_OBJECT (list),
reconcile_list_signals[TOGGLE_RECONCILED], split);
}

View File

@ -67,6 +67,8 @@ struct _GNCReconcileList
Account *account;
Query *query;
GNCReconcileList *sibling;
};
struct _GNCReconcileListClass

View File

@ -224,7 +224,7 @@ recnRecalculateBalance (RecnWindow *recnData)
gnc_numeric reconciled;
gnc_numeric diff;
GNCPrintAmountInfo print_info;
gboolean reverse_balance;
gboolean reverse_balance, include_children;
account = recn_get_account (recnData);
if (!account)
@ -233,7 +233,8 @@ recnRecalculateBalance (RecnWindow *recnData)
reverse_balance = gnc_reverse_balance(account);
/* update the starting balance */
starting = xaccAccountGetReconciledBalance(account);
include_children = xaccAccountGetReconcileChildrenStatus(account);
starting = gnc_ui_account_get_reconciled_balance(account, include_children);
print_info = gnc_account_print_info (account, TRUE);
if (reverse_balance)
@ -553,13 +554,14 @@ static gboolean
startRecnWindow(GtkWidget *parent, Account *account,
gnc_numeric *new_ending, time_t *statement_date)
{
GtkWidget *dialog, *end_value, *date_value;
GtkWidget *dialog, *end_value, *date_value, *include_children_button;
startRecnWindowData data = { NULL };
gboolean auto_interest_xfer_option;
GNCPrintAmountInfo print_info;
gnc_numeric ending;
char *title;
int result;
gboolean include_children;
/* Initialize the data structure that will be used for several callbacks
* throughout this file with the relevant info. Some initialization is
@ -575,7 +577,10 @@ startRecnWindow(GtkWidget *parent, Account *account,
auto_interest_xfer_option =
gnc_recn_interest_xfer_get_auto_interest_xfer_allowed( account );
ending = xaccAccountGetReconciledBalance(account);
include_children = xaccAccountGetReconcileChildrenStatus(account);
ending = gnc_ui_account_get_reconciled_balance(account,
include_children);
print_info = gnc_account_print_info (account, TRUE);
if (gnc_reverse_balance(account))
@ -610,10 +615,16 @@ startRecnWindow(GtkWidget *parent, Account *account,
GtkWidget *end_title = gtk_label_new(_("Ending Balance:"));
GtkWidget *start_value =
gtk_label_new(xaccPrintAmount (ending, print_info));
GtkWidget *blank_label = gtk_label_new("");
GtkWidget *vbox = GNOME_DIALOG(dialog)->vbox;
GtkWidget *entry;
GtkWidget *interest = NULL;
include_children_button =
gtk_check_button_new_with_label(_("Include Subaccounts"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(include_children_button),
include_children);
date_value = gnc_date_edit_new(*statement_date, FALSE, FALSE);
end_value = gnc_amount_edit_new ();
@ -655,10 +666,12 @@ startRecnWindow(GtkWidget *parent, Account *account,
gtk_box_pack_start(GTK_BOX(left_column), date_title, TRUE, TRUE, 3);
gtk_box_pack_start(GTK_BOX(left_column), start_title, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(left_column), end_title, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(left_column), blank_label, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(right_column), date_value, TRUE, TRUE, 3);
gtk_box_pack_start(GTK_BOX(right_column), start_value, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(right_column), end_value, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(right_column), include_children_button, TRUE, TRUE, 0);
/* if it's possible to enter an interest payment or charge for this
* account, add a button so that the user can pop up the appropriate
@ -707,6 +720,9 @@ startRecnWindow(GtkWidget *parent, Account *account,
if (gnc_reverse_balance(account))
*new_ending = gnc_numeric_neg (*new_ending);
xaccAccountSetReconcileChildrenStatus
(account, GTK_TOGGLE_BUTTON(include_children_button)->active);
}
/* cancel or delete */
@ -1604,7 +1620,10 @@ gnc_get_reconcile_info (Account *account,
/* if the account wasn't previously postponed, try to predict
* the statement balance based on the statement date.
*/
*new_ending = xaccAccountGetBalanceAsOfDate(account, *statement_date);
*new_ending =
gnc_ui_account_get_balance_as_of_date
(account, *statement_date,
xaccAccountGetReconcileChildrenStatus(account));
}
}
@ -1844,6 +1863,9 @@ recnWindow (GtkWidget *parent, Account *account)
(account, RECLIST_CREDIT, recnData,
&recnData->credit, &recnData->total_credit);
GNC_RECONCILE_LIST(recnData->debit)->sibling = GNC_RECONCILE_LIST(recnData->credit);
GNC_RECONCILE_LIST(recnData->credit)->sibling = GNC_RECONCILE_LIST(recnData->debit);
popup = gnc_recn_create_popup_menu(recnData);
gnome_popup_menu_attach(popup, recnData->debit, recnData);
gnome_popup_menu_attach(popup, recnData->credit, recnData);