Neil Williams' QOF Book Merge Patch #2.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@10311 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Derek Atkins 2004-10-31 19:19:44 +00:00
parent 23b612c6c5
commit 41de6f5c74
8 changed files with 165 additions and 124 deletions

View File

@ -1,3 +1,7 @@
2004-10-31 Derek Atkins <derek@ihtfp.com>
* Neil Williams' QOF Book Merge Patch #2.
2004-10-30 Christian Stimming <stimming@tuhh.de>
* doc/README.HBCI: Updated HBCI readme.

View File

@ -1255,6 +1255,27 @@ xaccAccountSetDescription (Account *acc, const char *str)
xaccAccountCommitEdit(acc);
}
void qofAccountSetParent (Account *acc, QofEntity *parent)
{
AccountGroup *ag;
if((!acc)||(!parent)) return;
if(acc->parent) return;
xaccAccountBeginEdit(acc);
g_message("qofAccountSetParent start");
ag = xaccAccountGetParent((Account*)parent);
acc->parent = ag;
/* FIXME: acc->parent is type AccountGroup but AccountGroup is not a true QOF object
so can't set AccountGroup in the target book because the GUID of any new AccountGroups
is not found. Workaround uses Account as the reference type.
*/
if(!acc->parent) {
g_message("qofAccountSetParent failed.");
}
mark_account (acc);
acc->inst.dirty = TRUE;
xaccAccountCommitEdit(acc);
}
void
xaccAccountSetNotes (Account *acc, const char *str)
{
@ -2854,19 +2875,23 @@ static QofObject account_object_def = {
gboolean xaccAccountRegister (void)
{
static QofParam params[] = {
{ ACCOUNT_NAME_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetName, (QofSetterFunc) xaccAccountSetName },
{ ACCOUNT_CODE_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetCode, (QofSetterFunc) xaccAccountSetCode },
{ ACCOUNT_DESCRIPTION_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetDescription, (QofSetterFunc) xaccAccountSetDescription },
{ ACCOUNT_NOTES_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetNotes, (QofSetterFunc) xaccAccountSetNotes },
{ ACCOUNT_PRESENT_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetPresentBalance, NULL },
{ ACCOUNT_BALANCE_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetBalance, NULL },
{ ACCOUNT_CLEARED_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetClearedBalance, NULL },
{ ACCOUNT_RECONCILED_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetReconciledBalance, NULL },
{ ACCOUNT_FUTURE_MINIMUM_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetProjectedMinimumBalance, NULL },
{ ACCOUNT_TAX_RELATED, QOF_TYPE_BOOLEAN, (QofAccessFunc)xaccAccountGetTaxRelated, (QofSetterFunc) xaccAccountSetTaxRelated },
{ QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
{ QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
{ ACCOUNT_KVP, QOF_TYPE_KVP, (QofAccessFunc)qof_instance_get_slots, NULL },
{ ACCOUNT_NAME_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetName, (QofSetterFunc) xaccAccountSetName },
{ ACCOUNT_CODE_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetCode, (QofSetterFunc) xaccAccountSetCode },
{ ACCOUNT_DESCRIPTION_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetDescription, (QofSetterFunc) xaccAccountSetDescription },
{ ACCOUNT_NOTES_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetNotes, (QofSetterFunc) xaccAccountSetNotes },
{ ACCOUNT_PRESENT_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetPresentBalance, NULL },
{ ACCOUNT_BALANCE_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetBalance, NULL },
{ ACCOUNT_CLEARED_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetClearedBalance, NULL },
{ ACCOUNT_RECONCILED_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetReconciledBalance, NULL },
{ ACCOUNT_TYPE_, QOF_TYPE_INT32, (QofAccessFunc)xaccAccountGetType, (QofSetterFunc)xaccAccountSetType },
{ ACCOUNT_FUTURE_MINIMUM_, QOF_TYPE_NUMERIC, (QofAccessFunc)xaccAccountGetProjectedMinimumBalance, NULL },
{ ACCOUNT_TAX_RELATED, QOF_TYPE_BOOLEAN, (QofAccessFunc)xaccAccountGetTaxRelated, (QofSetterFunc) xaccAccountSetTaxRelated },
{ ACCOUNT_SCU, QOF_TYPE_INT32, (QofAccessFunc)xaccAccountGetCommoditySCU, (QofSetterFunc)xaccAccountSetCommoditySCU },
{ ACCOUNT_NSCU, QOF_TYPE_BOOLEAN, (QofAccessFunc)xaccAccountSetNonStdSCU, (QofSetterFunc)xaccAccountSetNonStdSCU },
{ ACCOUNT_PARENT, GNC_ID_ACCOUNT, (QofAccessFunc)xaccAccountGetParentAccount, (QofSetterFunc)qofAccountSetParent },
{ QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
{ QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
{ ACCOUNT_KVP, QOF_TYPE_KVP, (QofAccessFunc)qof_instance_get_slots, NULL },
{ NULL },
};

View File

@ -212,9 +212,22 @@ void xaccAccountSetDescription (Account *account, const char *desc);
void xaccAccountSetNotes (Account *account, const char *notes);
/** Set the last num field of an Account */
void xaccAccountSetLastNum (Account *account, const char *num);
/** Set the account's type */
GNCAccountType xaccAccountGetType (Account *account);
/** \brief Special function only for qof_book_merge
qofAccountSetParent uses a specific QofEntity that is
set during a qof_book_merge and it refers to the
corresponding QofEntity in the target book. This is used
to link new accounts into an existing AccountGroup. The
parent reference is only changed if no parent exists.
Care is needed before this function can be used in any
other manner.
*/
void qofAccountSetParent (Account *, QofEntity *);
/** Get the account's name */
const char * xaccAccountGetName (Account *account);
/** Get the account's accounting code */
@ -727,7 +740,7 @@ const char * dxaccAccountGetQuoteTZ (Account *account);
/** @name Account parameter names */
/** @{ */
#define ACCOUNT_KVP "kvp"
#define ACCOUNT_KVP "kvp"
#define ACCOUNT_NAME_ "name"
#define ACCOUNT_CODE_ "code"
#define ACCOUNT_DESCRIPTION_ "desc"
@ -738,6 +751,11 @@ const char * dxaccAccountGetQuoteTZ (Account *account);
#define ACCOUNT_PRESENT_ "present"
#define ACCOUNT_FUTURE_MINIMUM_ "future-minimum"
#define ACCOUNT_TAX_RELATED "tax-related-p"
#define ACCOUNT_TYPE_ "account-type"
#define ACCOUNT_SCU "smallest-commodity-unit"
#define ACCOUNT_NSCU "non-standard-scu"
#define ACCOUNT_PARENT "parent-account"
/** @} */
/** This is the type-override when you want to match all accounts. Used

View File

@ -22,6 +22,7 @@
********************************************************************/
#include "qof_book_merge.h"
#include "qofid-p.h"
static short module = MOD_IMPORT;
/* all qof_book_merge data is held in mergeData. */
@ -277,26 +278,21 @@ qof_book_mergeUpdateRule(gboolean match)
int
qof_book_mergeCompare( void )
{
gchar *stringImport, *stringTarget,
*charImport, *charTarget;
char sa[GUID_ENCODING_LENGTH + 1];
const GUID *guidImport, *guidTarget;
QofInstance *inst;
gpointer unknown_obj;
QofParam *qtparam;
KvpFrame *kvpImport, *kvpTarget;
QofIdType mergeParamName;
QofType mergeType;
GSList *paramList;
QofEntity *mergeEnt, *targetEnt, *childEnt;
Timespec tsImport, tsTarget, (*date_getter) (QofEntity*, QofParam*);
gnc_numeric numericImport, numericTarget, (*numeric_getter) (QofEntity*, QofParam*);
double doubleImport, doubleTarget, (*double_getter) (QofEntity*, QofParam*);
gboolean absolute, mergeError,
knowntype, mergeMatch,
booleanImport, booleanTarget, (*boolean_getter) (QofEntity*, QofParam*);
gint32 i32Import, i32Target, (*int32_getter) (QofEntity*, QofParam*);
gint64 i64Import, i64Target, (*int64_getter) (QofEntity*, QofParam*);
gchar *stringImport, *stringTarget, *charImport, *charTarget;
QofEntity *mergeEnt, *targetEnt, *referenceEnt;
const GUID *guidImport, *guidTarget;
QofParam *qtparam;
KvpFrame *kvpImport, *kvpTarget;
QofIdType mergeParamName;
QofType mergeType;
GSList *paramList;
gboolean absolute, mergeError, knowntype, mergeMatch, booleanImport, booleanTarget,
(*boolean_getter) (QofEntity*, QofParam*);
Timespec tsImport, tsTarget, (*date_getter) (QofEntity*, QofParam*);
gnc_numeric numericImport, numericTarget, (*numeric_getter) (QofEntity*, QofParam*);
double doubleImport, doubleTarget, (*double_getter) (QofEntity*, QofParam*);
gint32 i32Import, i32Target, (*int32_getter) (QofEntity*, QofParam*);
gint64 i64Import, i64Target, (*int64_getter) (QofEntity*, QofParam*);
g_return_val_if_fail((mergeData != NULL)||(currentRule != NULL), -1);
absolute = currentRule->mergeAbsolute;
@ -401,26 +397,26 @@ qof_book_mergeCompare( void )
qof_book_mergeUpdateRule(mergeMatch);
knowntype= TRUE;
}
/* no need to verify the book */
if(safe_strcmp(mergeType, QOF_ID_BOOK) == 0) { knowntype= TRUE; }
/* deal with non-QOF type parameters : */
/* references to other registered QOF objects */
/* deal with custom type parameters : */
/* using references to other registered QOF objects */
/* these references are NOT compared again here, just stored for the commit. */
if(knowntype == FALSE) {
if(qof_class_is_registered(currentRule->mergeLabel)) {
childEnt = g_new(QofEntity,1);
unknown_obj = qtparam->param_getfcn(mergeEnt, qtparam);
inst = ((QofInstance*)(unknown_obj));
childEnt = &inst->entity;
currentRule->linkedEntList = g_slist_prepend(currentRule->linkedEntList, childEnt);
guidImport = qof_entity_get_guid(childEnt);
if(guidImport != NULL) {
guid_to_string_buff(guidImport, sa);
stringImport = g_strdup(sa);
printf("Test routine GUID: %s\n", stringImport);
referenceEnt = g_new(QofEntity,1);
referenceEnt = qtparam->param_getfcn(targetEnt, qtparam);
if(referenceEnt != NULL) {
if(referenceEnt->e_type != NULL) {
if(safe_strcmp(referenceEnt->e_type, mergeType) != 0) {
referenceEnt->e_type = NULL;
g_free(referenceEnt);
}
}
}
/* add to the rule so that the reference can be picked up in commit */
if(referenceEnt) {
currentRule->linkedEntList = g_slist_prepend(currentRule->linkedEntList, referenceEnt);
}
}
g_return_val_if_fail(knowntype == TRUE, -1);
paramList = g_slist_next(paramList);
}
g_free(kvpImport);
@ -621,9 +617,11 @@ void qof_book_mergeCommitRuleLoop(qof_book_mergeRule *rule, guint remainder)
{
QofInstance *inst;
gboolean registered_type;
QofEntity *referenceEnt;
GSList *linkage;
/* cm_ prefix used for variables that hold the data to commit */
QofParam *cm_param;
char *cm_string, *cm_char;
gchar *cm_string, *cm_char;
const GUID *cm_guid;
KvpFrame *cm_kvp;
/* function pointers and variables for parameter getters that don't use pointers normally */
@ -644,23 +642,26 @@ void qof_book_mergeCommitRuleLoop(qof_book_mergeRule *rule, guint remainder)
void (*i64_setter) (QofEntity*, gint64);
void (*char_setter) (QofEntity*, char*);
void (*kvp_frame_setter) (QofEntity*, KvpFrame*);
void (*reference_setter) (QofEntity*, QofEntity*);
g_return_if_fail(rule != NULL);
g_return_if_fail((rule->mergeResult != MERGE_NEW)||(rule->mergeResult != MERGE_UPDATE));
/* create a new object for MERGE_NEW */
/* create a new object for MERGE_NEW */
/* The new object takes the GUID from the import to retain an absolute match */
if(rule->mergeResult == MERGE_NEW) {
inst = (QofInstance*)qof_object_new_instance(rule->importEnt->e_type, mergeData->targetBook);
g_return_if_fail(inst != NULL);
rule->targetEnt = &inst->entity;
qof_entity_set_guid(rule->targetEnt, qof_entity_get_guid(rule->importEnt));
}
/* currentRule->targetEnt is now set,
1. by an absolute GUID match or
2. by best_matchEnt and difference or
3. by MERGE_NEW.
*/
registered_type = FALSE;
while(rule->mergeParam != NULL) {
registered_type = FALSE;
g_return_if_fail(rule->mergeParam->data);
cm_param = rule->mergeParam->data;
rule->mergeType = cm_param->param_type;
@ -732,24 +733,14 @@ void qof_book_mergeCommitRuleLoop(qof_book_mergeRule *rule, guint remainder)
registered_type = TRUE;
}
if(registered_type == FALSE) {
if(qof_class_is_registered(rule->mergeLabel)) {
/* need to lookup childEnt in the target book to
ensure it has the right QofCollection */
GSList *linkage = g_slist_copy(rule->linkedEntList);
while(linkage != NULL) {
QofEntity *childEnt = linkage->data;
/* there may be more than one linked QofEntity for this rule */
if(safe_strcmp(childEnt->e_type, rule->mergeType) == 0) {
cm_guid = qof_entity_get_guid(childEnt);
QofCollection *col;
col = qof_book_get_collection (mergeData->targetBook, rule->mergeType);
childEnt = qof_collection_lookup_entity (col, cm_guid);
/* childEnt isn't used here yet. It may be too early to set */
/* intention is to set the parameter if childEnt is not null.
might have to store the param and set later, after Commit. */
}
linkage = g_slist_next(linkage);
linkage = g_slist_copy(rule->linkedEntList);
while(linkage != NULL) {
referenceEnt = linkage->data;
if(safe_strcmp(referenceEnt->e_type, rule->mergeType) == 0) {
reference_setter = (void(*)(QofEntity*, QofEntity*))cm_param->param_setfcn;
if(reference_setter != NULL) { reference_setter(rule->targetEnt, referenceEnt); }
}
linkage = g_slist_next(linkage);
}
}
rule->mergeParam = g_slist_next(rule->mergeParam);

View File

@ -72,7 +72,10 @@ any error values to the calling process.
#include <glib.h>
#include "qof.h"
#include "qof/gnc-engine-util.h"
#include "qofbook.h"
#include "qofclass.h"
#include "qofobject.h"
#include "qofinstance-p.h"
#include "gnc-trace.h"

View File

@ -44,6 +44,7 @@
#include "global-options.h"
#include "io-example-account.h"
#include "top-level.h"
#include "qofbook.h"
#include "gnc-trace.h"
static short module = MOD_IMPORT;
@ -51,7 +52,7 @@ static short module = MOD_IMPORT;
static GtkWidget *hierarchy_window = NULL;
GtkWidget *qof_book_merge_window = NULL;
static AccountGroup *our_final_group = NULL;
QofBook *temporary;
static void on_balance_changed (GNCAmountEdit *gae);
@ -386,7 +387,8 @@ on_choose_account_types_prepare (GnomeDruidPage *gnomedruidpage,
gchar *locale_dir = gnc_get_ea_locale_dir (GNC_ACCOUNTS_DIR);
gnc_suspend_gui_refresh ();
list = gnc_load_example_account_list (gnc_get_current_book (),
temporary = qof_book_new();
list = gnc_load_example_account_list (temporary,
locale_dir);
gnc_resume_gui_refresh ();
@ -917,12 +919,14 @@ on_finish (GnomeDruidPage *gnomedruidpage,
if (our_final_group)
xaccGroupForEachAccount (our_final_group, starting_balance_helper,
NULL, TRUE);
ENTER (" ");
qof_book_merge_window = gtk_object_get_data (GTK_OBJECT (hierarchy_window), "Merge Druid");
if(qof_book_merge_window) {
DEBUG ("qof_book_merge_window found");
if (our_final_group)
xaccGroupConcatGroup (gnc_get_current_group (), our_final_group);
gtk_widget_show(qof_book_merge_window);
qof_book_destroy(temporary);
delete_hierarchy_window ();
gnc_resume_gui_refresh ();
LEAVE (" ");
@ -936,6 +940,7 @@ on_finish (GnomeDruidPage *gnomedruidpage,
if (our_final_group)
xaccGroupConcatGroup (gnc_get_current_group (), our_final_group);
qof_book_destroy(temporary);
gnc_resume_gui_refresh ();
LEAVE (" ");
@ -1045,6 +1050,5 @@ gnc_ui_hierarchy_druid (void)
hierarchy_window = gnc_create_hierarchy_druid ();
// qof_book_merge_window = qof_book_merge_running();
return;
}

View File

@ -36,9 +36,10 @@
#include "gnc-gui-query.h"
#include "qof_book_merge.h"
#include "druid-hierarchy.h"
#include "gnc-ui-util.h"
#include "Account.h"
#include "global-options.h"
#include "gnc-trace.h"
//static short module = MOD_IMPORT;
static GtkWidget *qof_book_merge_window = NULL;
static GtkWidget *druid_hierarchy_window = NULL;
@ -52,45 +53,6 @@ static gchar *buffer = "";
void collision_rule_loop ( qof_book_mergeRule*, guint );
void progress_rule_loop ( qof_book_mergeRule*, guint );
void summary_ForeachParam ( QofParam*, gpointer );
void summary_ForeachType ( QofObject*, gpointer );
void summary_Foreach ( QofEntity*, gpointer );
void
summary_ForeachParam( QofParam* param, gpointer user_data)
{
QofEntity *ent;
char *importstring;
ent = (QofEntity*)user_data;
/* To control the amount of output, only strings are
printed in this example. Remove the loop for all
data.
*/
if(safe_strcmp(param->param_type,QOF_TYPE_STRING) == 0) {
importstring = NULL;
importstring = qof_book_merge_param_as_string(param, ent);
printf("%-20s\t\t%s\t\t%s\n", param->param_name, param->param_type, importstring);
}
}
void
summary_Foreach ( QofEntity* ent, gpointer user_data)
{
qof_class_param_foreach(ent->e_type, summary_ForeachParam , ent);
}
void
summary_ForeachType ( QofObject* obj, gpointer user_data)
{
QofBook *book;
book = (QofBook*)user_data;
printf("\n%s\n", obj->e_type);
printf("Parameter name\t\t\tData type\t\tValue\n");
qof_object_foreach(obj->e_type, book, summary_Foreach, NULL);
}
static GtkWidget*
merge_get_widget (const char *name)
@ -184,8 +146,8 @@ on_qof_book_merge_next (GnomeDruidPage *gnomedruidpage,
}
static void
on_cancel (GnomeDruid *gnomedruid,
gpointer user_data)
on_cancel ( GnomeDruid *gnomedruid,
gpointer user_data)
{
gnc_suspend_gui_refresh ();
delete_merge_window();
@ -195,17 +157,49 @@ on_cancel (GnomeDruid *gnomedruid,
gnc_resume_gui_refresh ();
}
void currency_transfer_cb ( QofEntity* ent, gpointer user_data)
{
if(!ent) return;
if(xaccAccountGetCommodity((Account*)ent) == NULL) {
xaccAccountSetCommodity((Account*)ent, gnc_default_currency());
}
}
void reference_parent_cb ( QofEntity* ent, gpointer user_data)
{
if(!ent) return;
if(xaccAccountGetParent((Account*)ent) == NULL) {
xaccGroupInsertAccount(xaccGroupGetRoot(xaccGetAccountGroup(gnc_get_current_book())), (Account*)ent);
}
}
static void
on_finish (GnomeDruidPage *gnomedruidpage,
gpointer arg1,
gpointer user_data)
{
gint result;
GtkWidget *top;
const char *message = _("Error: the Commit operation failed.");
gnc_suspend_gui_refresh ();
qof_book_mergeCommit();
result = qof_book_mergeCommit();
if(result != 0) {
top = gtk_widget_get_toplevel (GTK_WIDGET (gnomedruidpage));
gnc_error_dialog(top, message);
}
delete_merge_window ();
/*
Account has a new setparent parameter that takes
a QofEntity. Account converts this into an AccountGroup based on
the GUID in the reference. This needs improving as child accounts
are currently being re-parented to top-level.
*/
qof_session_set_current_session(previous_session);
qof_object_foreach(GNC_ID_ACCOUNT, gnc_get_current_book(), reference_parent_cb, NULL);
qof_object_foreach(GNC_ID_ACCOUNT, gnc_get_current_book(), currency_transfer_cb, NULL);
qof_book_destroy(mergeBook);
qof_session_end(merge_session);
qof_session_end(merge_session);
gnc_resume_gui_refresh ();
}
@ -247,9 +241,6 @@ gnc_create_merge_druid (void)
glade_xml_signal_connect(xml, "on_start_page_next",
GTK_SIGNAL_FUNC (on_qof_start_page_next));
// Please resolve these conflicts in the merge
// on_qof_book_merge_prepare
glade_xml_signal_connect(xml, "on_qof_book_merge_prepare",
GTK_SIGNAL_FUNC (on_qof_book_merge_prepare));
@ -431,6 +422,5 @@ gnc_ui_qof_book_merge_druid (void)
g_return_if_fail(targetBook != NULL);
g_return_if_fail(mergeBook != NULL);
g_return_if_fail(merge_session != NULL);
gnc_set_log_level(MOD_IMPORT, GNC_LOG_WARNING);
return;
}

View File

@ -75,6 +75,12 @@ any error values to the calling process.
void gnc_ui_qof_book_merge_druid (void);
GtkWidget* qof_book_merge_running (void);
/** \brief gncCommodity is not QOF enabled, need to set a default commodity before the merge */
void currency_transfer_cb ( QofEntity* ent, gpointer user_data);
/** \brief workaround for AccountGroup not being fully QOF enabled. */
void reference_parent_cb ( QofEntity* ent, gpointer user_data);
/** @} */
/** @} */