add utilities for accounting periods, clean up backend handling

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@6034 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Linas Vepstas 2001-11-25 01:38:58 +00:00
parent 3a7fa14de0
commit aa232f2fcf
8 changed files with 133 additions and 99 deletions

View File

@ -30,6 +30,7 @@
#include "BackendP.h"
#include "Group.h"
#include "GroupP.h"
#include "gnc-book-p.h"
#include "gnc-engine-util.h"
#include "gnc-pricedb.h"
#include "gnc-pricedb-p.h"
@ -71,28 +72,23 @@ xaccBackendGetError (Backend *be)
Backend *
xaccAccountGetBackend (Account * acc)
{
Account *parent_acc;
AccountGroup * grp;
if (!acc) return NULL;
grp = xaccAccountGetRoot (acc);
if (!grp || !grp->book) return NULL;
/* find the first account group that has a backend */
grp = acc->parent;
while (grp) {
if (grp->backend) return (grp->backend);
parent_acc = grp -> parent;
grp = NULL;
if (parent_acc) {
grp = parent_acc->parent;
}
}
return NULL;
return grp->book->backend;
}
/********************************************************************\
* Fetch the backend *
\********************************************************************/
/* XXX hack alert -- practically, it would be easier if we found the
* book, and then asked the book about the backend.
*/
Backend *
xaccTransactionGetBackend (Transaction *trans)
{
@ -124,11 +120,6 @@ xaccTransactionGetBackend (Transaction *trans)
}
if (!s) return NULL;
/* I suppose it would be more 'technically correct' to make sure that
* all splits share the same backend, and flag an error if they
* don't. However, at this point, it seems quite unlikely, so we'll
* just use the first backend we find.
*/
return xaccAccountGetBackend (xaccSplitGetAccount(s));
}
@ -136,25 +127,12 @@ xaccTransactionGetBackend (Transaction *trans)
* Set the backend *
\********************************************************************/
void
xaccGroupSetBackend (AccountGroup *grp, Backend *be)
{
if (!grp) return;
grp->backend = be;
}
Backend *
xaccGroupGetBackend (AccountGroup *grp)
{
while (grp)
{
Account *parent;
if (grp->backend) return (grp->backend);
parent = grp->parent;
if (!parent) return NULL;
grp = parent->parent;
}
return NULL;
grp = xaccGroupGetRoot (grp);
if (!grp || !grp->book) return NULL;
return grp->book->backend;
}
/********************************************************************\

View File

@ -215,10 +215,6 @@ GNCBackendError xaccBackendGetError (Backend *be);
Backend * xaccAccountGetBackend (Account *account);
Backend * xaccTransactionGetBackend (Transaction *trans);
/*
* The xaccGroupSetBackend() associates a backend to a group
*/
void xaccGroupSetBackend (AccountGroup *group, Backend *be);
Backend * xaccGroupGetBackend (AccountGroup *group);
Backend * xaccGNCBookGetBackend (GNCBook *book);

View File

@ -52,42 +52,29 @@ static short module = MOD_ENGINE;
\********************************************************************/
static void
xaccInitializeAccountGroup (AccountGroup *grp, GNCEntityTable *entity_table)
xaccInitializeAccountGroup (AccountGroup *grp, GNCBook *book)
{
grp->saved = 1;
grp->parent = NULL;
grp->accounts = NULL;
grp->backend = NULL;
grp->book = NULL;
grp->entity_table = entity_table;
grp->book = book;
}
/********************************************************************\
\********************************************************************/
static AccountGroup *
xaccMallocAccountGroupEntityTable (GNCEntityTable *entity_table)
{
AccountGroup *grp;
g_return_val_if_fail (entity_table, NULL);
grp = g_new (AccountGroup, 1);
xaccInitializeAccountGroup (grp, entity_table);
return grp;
}
AccountGroup *
xaccMallocAccountGroup (GNCBook *book)
{
AccountGroup *grp;
g_return_val_if_fail (book, NULL);
return xaccMallocAccountGroupEntityTable
(gnc_book_get_entity_table (book));
grp = g_new (AccountGroup, 1);
xaccInitializeAccountGroup (grp, book);
return grp;
}
/********************************************************************\
@ -242,8 +229,9 @@ xaccAccountGetBook (Account *account)
if (!account) return NULL;
group = xaccAccountGetParent (account);
if (!group) return NULL;
return xaccGroupGetBook (group);
return group->book;
}
/********************************************************************\
@ -400,7 +388,7 @@ xaccGroupGetSubAccounts (AccountGroup *grp)
return g_list_reverse (accounts);
}
GList *
AccountList *
xaccGroupGetAccountList (AccountGroup *grp)
{
if (!grp) return NULL;
@ -413,16 +401,11 @@ xaccGroupGetAccountList (AccountGroup *grp)
\********************************************************************/
AccountGroup *
xaccAccountGetRoot (Account * acc)
xaccGroupGetRoot (AccountGroup * grp)
{
AccountGroup * grp;
AccountGroup * root = NULL;
if (!acc) return NULL;
/* find the root of the account group structure */
grp = acc->parent;
while (grp)
{
Account *parent_acc;
@ -439,6 +422,13 @@ xaccAccountGetRoot (Account * acc)
return root;
}
AccountGroup *
xaccAccountGetRoot (Account * acc)
{
if (!acc) return NULL;
return xaccGroupGetRoot (acc->parent);
}
/********************************************************************\
* Fetch an account, given its name *
\********************************************************************/
@ -632,7 +622,8 @@ void
xaccGroupRemoveAccount (AccountGroup *grp, Account *acc)
{
if (!acc) return;
/* this routine might be called on accounts which
/* Note this routine might be called on accounts which
* are not yet parented. */
if (!grp) return;
@ -667,16 +658,18 @@ xaccGroupRemoveAccount (AccountGroup *grp, Account *acc)
void
xaccAccountInsertSubAccount (Account *adult, Account *child)
{
if (!adult || !child) return;
if (!adult) return;
/* We want the parent to have an entity table. It doesn't have to
* be the same entity table as the child, the xaccGroupInsertAccount
* routine will take care of that. */
g_return_if_fail (adult->entity_table);
g_return_if_fail (adult->entity_table == child->entity_table);
/* if a container for the children doesn't yet exist, add it */
if (adult->children == NULL)
{
adult->children = xaccMallocAccountGroupEntityTable (adult->entity_table);
xaccGroupSetBook (adult->children, xaccGroupGetBook (adult->parent));
GNCBook *book = xaccGroupGetBook (adult->parent);
adult->children = xaccMallocAccountGroup (book);
}
/* set back-pointer to parent */
@ -706,11 +699,9 @@ group_sort_helper (gconstpointer a, gconstpointer b)
void
xaccGroupInsertAccount (AccountGroup *grp, Account *acc)
{
if (!grp) return;
if (!grp || !grp->book) return;
if (!acc) return;
g_return_if_fail (grp->entity_table == acc->entity_table);
/* If the account is currently in another group, remove it there
* first. Basically, we can't have accounts being in two places at
* once. If old and new parents are the same, reinsertion causes
@ -724,8 +715,28 @@ xaccGroupInsertAccount (AccountGroup *grp, Account *acc)
xaccAccountBeginEdit (acc);
if (acc->parent)
{
xaccGroupRemoveAccount (acc->parent, acc);
/* switch over entity tables if needed */
if (grp->book->entity_table != acc->entity_table)
{
/* hack alert -- this implementation is not exactly correct.
* If the entity tables are not identical, then the 'from' book
* will have a different backend than the 'to' book. This means
* that we should get the 'from' backend to destroy this account,
* and the 'to' backend to save it. Right now, this is broken.
*/
PWARN ("reparenting accounts accross books is not correctly supported\n");
gnc_engine_generate_event (&acc->guid, GNC_EVENT_DESTROY);
xaccRemoveEntity (acc->entity_table, &acc->guid);
xaccStoreEntity (grp->book->entity_table, acc, &acc->guid, GNC_ID_ACCOUNT);
gnc_engine_generate_event (&acc->guid, GNC_EVENT_CREATE);
}
}
/* set back-pointer to the account's parent */
acc->parent = grp;
@ -738,7 +749,7 @@ xaccGroupInsertAccount (AccountGroup *grp, Account *acc)
grp->saved = 0;
xaccGroupSetBook (acc->children, xaccGroupGetBook (grp));
xaccGroupSetBook (acc->children, grp->book);
gnc_engine_generate_event (&acc->guid, GNC_EVENT_MODIFY);
}
@ -752,10 +763,10 @@ xaccGroupConcatGroup (AccountGroup *togrp, AccountGroup *fromgrp)
if (!togrp) return;
if (!fromgrp) return;
g_return_if_fail (togrp->entity_table == fromgrp->entity_table);
/* The act of inserting the account into togrp also causes it to
* automatically be deleted from fromgrp. Be careful! */
* automatically be deleted from fromgrp. This causes linked
* lists to be re-written, and so a cursor traversal is not safe.
* Be careful! */
while (TRUE)
{
@ -764,8 +775,7 @@ xaccGroupConcatGroup (AccountGroup *togrp, AccountGroup *fromgrp)
GList *next;
accounts = fromgrp->accounts;
if (!accounts)
return;
if (!accounts) return;
next = accounts->next;
@ -773,14 +783,39 @@ xaccGroupConcatGroup (AccountGroup *togrp, AccountGroup *fromgrp)
xaccGroupInsertAccount (togrp, account);
if (!next)
return;
if (!next) return;
}
}
/********************************************************************\
\********************************************************************/
void
xaccGroupCopyGroup (AccountGroup *to, AccountGroup *from)
{
GList *node;
if (!to || !from) return;
if (!from->accounts || !to->book) return;
for (node = from->accounts; node; node=node->next)
{
Account *to_acc, *from_acc = node->data;
to_acc = xaccCloneAccountSimple (from_acc, to->book);
xaccAccountBeginEdit (to_acc);
to->accounts = g_list_append (to->accounts, to_acc);
if (from_acc->children)
{
to_acc->children = xaccMallocAccountGroup (to->book);
xaccGroupCopyGroup (to_acc->children, from_acc->children);
}
xaccAccountCommitEdit (to_acc);
}
}
/********************************************************************\
\********************************************************************/
void
xaccGroupMergeAccounts (AccountGroup *grp)
{

View File

@ -43,8 +43,16 @@ void xaccAccountGroupBeginEdit (AccountGroup *grp);
void xaccAccountGroupCommitEdit (AccountGroup *grp);
/*
* The xaccGroupConcatGroup() subroutine will move all accounts
* from the "from" group to the "to" group
* The xaccGroupConcatGroup() subroutine will move (reparent)
* all accounts from the "from" group to the "to" group,
* preserving the account heirarchy. It will also take care
* that the moved accounts will have the "to" group's book
* parent as well.
*
* The xaccGroupCopyGroup() subroutine will copy all accounts
* from the "from" group to the "to" group, preserving the
* account heirarchy. It will also take care that the moved
* accounts will have the "to" groups book parent as well.
*
* The xaccGroupMergeAccounts() subroutine will go through a group,
* merging all accounts that have the same name and description.
@ -52,6 +60,7 @@ void xaccAccountGroupCommitEdit (AccountGroup *grp);
*/
void xaccGroupConcatGroup (AccountGroup *to, AccountGroup *from);
void xaccGroupCopyGroup (AccountGroup *to, AccountGroup *from);
void xaccGroupMergeAccounts (AccountGroup *grp);
/*
@ -90,6 +99,18 @@ void xaccGroupMarkDoFree (AccountGroup *grp);
* account group can now be reparented to a new location.
* Note, however, that it will mark the old parents as having
* been modified.
*
* The xaccGroupInsertAccount() subroutine will insert the indicated
* account into the indicated group. If it already is the child
* of another group, it will be removed there first. If the
* account belongs to a different book than the the group, it
* will be removed from the other book (and thus, the other book's
* entity tables, generating destroy & create events). If the
* account is removed from and inserted into the same group, the
* overall account sort order will be recomputed.
*
* The xaccAccountInsertSubAccount() does the same, except that
* the parent is specified as an account.
*/
void xaccGroupRemoveAccount (AccountGroup *grp, Account *account);
@ -157,9 +178,13 @@ Account *xaccGetPeerAccountFromFullName (Account *acc,
const char separator);
/*
* The xaccGetAccountRoot () subroutine will find the topmost
* The xaccGroupGetRoot() subroutine will find the topmost
* (root) group to which this group belongs.
*
* The xaccGetAccountRoot() subroutine will find the topmost
* (root) group to which this account belongs.
*/
AccountGroup * xaccGroupGetRoot (AccountGroup *grp);
AccountGroup * xaccAccountGetRoot (Account *account);
/* The xaccGroupGetParentAccount() subroutine returns the parent

View File

@ -51,15 +51,10 @@ struct account_group_s
/* The flags: */
unsigned int saved : 1;
GNCEntityTable *entity_table; /* table which child accounts must
* be stored in. */
Account *parent; /* back-pointer to parent */
AccountList *accounts; /* list of account pointers */
Backend *backend; /* persistant storage backend */
GNCBook *book; /* The book which this group belongs to */
};

View File

@ -36,18 +36,27 @@ GNCBook * gnc_book_partition (GNCBook *, Query *);
#endif XACC_PERIOD_H__
#include "gnc-book-p.h"
#include "GroupP.h"
/* ================================================================ */
GNCBook *
gnc_book_partition (GNCBook *existing_book, Query *query)
{
GNCBook *partition_book;
AccountGroup *part_topgrp;
if (!existing_book || !query) return NULL;
partition_book = gnc_book_new();
/* first, copy all of the accounts */
xaccGroupCopyGroup (partition_book->topgroup, existing_book->topgroup);
return partition_book;
}
/* ================================================================ */
/* ============================= END OF FILE ====================== */

View File

@ -32,6 +32,7 @@
#include <sys/time.h>
#include <unistd.h>
#include "gnc-book-p.h"
#include "gnc-engine-util.h"
#include "gnc-numeric.h"
#include "AccountP.h"
@ -1073,7 +1074,7 @@ guid_list_to_account_list (Query * q, GList *guids)
GList *accounts = NULL;
GList *node;
if (!q || !q->acct_group)
if (!q || !q->acct_group || !q->acct_group->book)
return NULL;
for (node = guids; node; node = node->next)
@ -1084,7 +1085,7 @@ guid_list_to_account_list (Query * q, GList *guids)
if (!guid)
continue;
account = xaccAccountLookupEntityTable (guid, q->acct_group->entity_table);
account = xaccAccountLookupEntityTable (guid, q->acct_group->book->entity_table);
if (!account)
continue;

View File

@ -192,8 +192,6 @@ gnc_book_set_group (GNCBook *book, AccountGroup *grp)
xaccGroupSetBook (grp, book);
book->topgroup = grp;
xaccGroupSetBackend (grp, book->backend);
}
void
@ -202,7 +200,6 @@ gnc_book_set_backend (GNCBook *book, Backend *be)
if (!book) return;
book->backend = be;
xaccGroupSetBackend (book->topgroup, be);
xaccPriceDBSetBackend (book->pricedb, be);
}
@ -279,8 +276,6 @@ gnc_book_set_template_group (GNCBook *book, AccountGroup *templateGroup)
xaccGroupSetBook (templateGroup, book);
book->template_group = templateGroup;
xaccGroupSetBackend (templateGroup, book->backend);
}
Backend *