mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
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:
parent
3a7fa14de0
commit
aa232f2fcf
@ -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;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,8 +783,33 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
@ -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 ====================== */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 *
|
||||
|
Loading…
Reference in New Issue
Block a user