Merge branch 'private-kvp' into master again

This was done by branching right before the original merge
and redoing a clean merge of the private-kvp branch again.

This result was then cherry-picked onto master with
git cherry-pick <merge-commit> -m 1

It was done like this because git merge would consider
the private-kvp branch already merged even after a revert
(see git-revert man page) and won't allow to merge a
second time on the same branch.

Resolved conflicts:
	README.dependencies
	src/app-utils/gnc-sx-instance-model.c
	src/engine/cap-gains.c
	src/engine/test/Makefile.am
	src/gnome/assistant-hierarchy.c
	src/import-export/import-match-map.c
	src/import-export/import-utilities.c
	src/import-export/ofx/gnc-ofx-kvp.c
	src/libqof/qof/qofbook.cpp
	src/libqof/qof/qofinstance-p.h
	src/libqof/qof/qofinstance.cpp
	src/libqof/qof/test/test-kvp_frame.c
	src/report/report-gnome/gnc-plugin-page-report.c
This commit is contained in:
Geert Janssens 2014-05-07 15:37:14 +02:00
parent ae98012d0c
commit 45cb5504f3
117 changed files with 4069 additions and 2273 deletions

View File

@ -404,7 +404,6 @@ src/import-export/import-backend.c
src/import-export/import-commodity-matcher.c
src/import-export/import-format-dialog.c
src/import-export/import-main-matcher.c
src/import-export/import-match-map.c
src/import-export/import-match-picker.c
src/import-export/import-parse.c
src/import-export/import-settings.c

View File

@ -33,7 +33,7 @@ GncTaxTable* gnc_business_get_default_tax_table (QofBook *book, GncOwnerType own
GNCOptionDB *odb;
odb = gnc_option_db_new_for_type (GNC_ID_BOOK);
gnc_option_db_load_from_kvp (odb, qof_book_get_slots (book));
qof_book_load_options (book, gnc_option_db_load_from_kvp, odb);
switch (ownertype)
{

View File

@ -102,15 +102,13 @@ get_fy_end(void)
{
QofBook *book;
KvpFrame *book_frame;
gint64 month, day;
GDate *date = NULL;
book = gnc_get_current_book();
book_frame = qof_book_get_slots(book);
month = kvp_frame_get_gint64(book_frame, "/book/fyear_end/month");
day = kvp_frame_get_gint64(book_frame, "/book/fyear_end/day");
if (g_date_valid_dmy(day, month, 2005 /* not leap year */))
return g_date_new_dmy(day, month, G_DATE_BAD_YEAR);
return NULL;
qof_instance_get (QOF_INSTANCE (book),
"fy-end", &date,
NULL);
return date;
}
time64

View File

@ -176,10 +176,9 @@ _get_vars_helper(Transaction *txn, void *var_hash_data)
{
GHashTable *var_hash = (GHashTable*)var_hash_data;
GList *split_list;
kvp_frame *kvpf;
kvp_value *kvp_val;
Split *s;
char *str;
gchar *credit_formula = NULL;
gchar *debit_formula = NULL;
gnc_commodity *first_cmdty = NULL;
split_list = xaccTransGetSplitList(txn);
@ -191,16 +190,16 @@ _get_vars_helper(Transaction *txn, void *var_hash_data)
for ( ; split_list; split_list = split_list->next)
{
gnc_commodity *split_cmdty = NULL;
GncGUID *acct_guid;
GncGUID *acct_guid = NULL;
Account *acct;
s = (Split*)split_list->data;
kvpf = xaccSplitGetSlots(s);
kvp_val = kvp_frame_get_slot_path(kvpf,
GNC_SX_ID,
GNC_SX_ACCOUNT,
NULL);
acct_guid = kvp_value_get_guid(kvp_val);
qof_instance_get (QOF_INSTANCE (s),
"sx-account", &acct_guid,
"sx-credit-formula", &credit_formula,
"sx-debit-formula", &debit_formula,
NULL);
acct = xaccAccountLookup(acct_guid, gnc_get_current_book());
split_cmdty = xaccAccountGetCommodity(acct);
if (first_cmdty == NULL)
@ -226,31 +225,16 @@ _get_vars_helper(Transaction *txn, void *var_hash_data)
}
// existing... ------------------------------------------
kvp_val = kvp_frame_get_slot_path(kvpf,
GNC_SX_ID,
GNC_SX_CREDIT_FORMULA,
NULL);
if (kvp_val != NULL)
{
str = kvp_value_get_string(kvp_val);
if (str && strlen(str) != 0)
{
gnc_sx_parse_vars_from_formula(str, var_hash, NULL);
}
}
kvp_val = kvp_frame_get_slot_path(kvpf,
GNC_SX_ID,
GNC_SX_DEBIT_FORMULA,
NULL);
if (kvp_val != NULL)
{
str = kvp_value_get_string(kvp_val);
if (str && strlen(str) != 0)
{
gnc_sx_parse_vars_from_formula(str, var_hash, NULL);
}
}
if (credit_formula && strlen(credit_formula) != 0)
{
gnc_sx_parse_vars_from_formula(credit_formula, var_hash, NULL);
}
if (debit_formula && strlen(debit_formula) != 0)
{
gnc_sx_parse_vars_from_formula(debit_formula, var_hash, NULL);
}
g_free (credit_formula);
g_free (debit_formula);
}
return 0;
@ -900,31 +884,15 @@ typedef struct _SxTxnCreationData
} SxTxnCreationData;
static gboolean
_get_template_split_account(const SchedXaction* sx, const Split *template_split, Account **split_acct, GList **creation_errors)
_get_template_split_account(const SchedXaction* sx,
const Split *template_split,
Account **split_acct,
GList **creation_errors)
{
GncGUID *acct_guid;
kvp_frame *split_kvpf;
kvp_value *kvp_val;
split_kvpf = xaccSplitGetSlots(template_split);
/* contains the guid of the split's actual account. */
kvp_val = kvp_frame_get_slot_path(split_kvpf,
GNC_SX_ID,
GNC_SX_ACCOUNT,
NULL);
if (kvp_val == NULL)
{
GString *err = g_string_new("");
g_string_printf(err, "Null account kvp value for SX [%s], cancelling creation.",
xaccSchedXactionGetName(sx));
g_critical("%s", err->str);
if (creation_errors != NULL)
*creation_errors = g_list_append(*creation_errors, err);
else
g_string_free(err, TRUE);
return FALSE;
}
acct_guid = kvp_value_get_guid( kvp_val );
GncGUID *acct_guid = NULL;
qof_instance_get (QOF_INSTANCE (template_split),
"sx-account", &acct_guid,
NULL);
*split_acct = xaccAccountLookup(acct_guid, gnc_get_current_book());
if (*split_acct == NULL)
{
@ -946,34 +914,34 @@ _get_template_split_account(const SchedXaction* sx, const Split *template_split,
}
static void
_get_sx_formula_value(const SchedXaction* sx, const Split *template_split, gnc_numeric *numeric, GList **creation_errors, const char *formula_key, const char* numeric_key, GHashTable *variable_bindings)
_get_sx_formula_value(const SchedXaction* sx,
const Split *template_split,
gnc_numeric *numeric,
GList **creation_errors,
const char *formula_key,
const char* numeric_key,
GHashTable *variable_bindings)
{
kvp_frame *split_kvpf;
kvp_value *kvp_val;
char *formula_str, *parseErrorLoc;
split_kvpf = xaccSplitGetSlots(template_split);
char *formula_str = NULL, *parseErrorLoc = NULL;
gnc_numeric *numeric_val = NULL;
qof_instance_get (QOF_INSTANCE (template_split),
formula_key, &formula_str,
numeric_key, &numeric_val,
NULL);
/* First look up the gnc_numeric value in the template split */
kvp_val = kvp_frame_get_slot_path(split_kvpf,
GNC_SX_ID,
numeric_key,
NULL);
*numeric = kvp_value_get_numeric(kvp_val);
if ((gnc_numeric_check(*numeric) == GNC_ERROR_OK)
&& !gnc_numeric_zero_p(*numeric))
if (numeric_val != NULL &&
gnc_numeric_check(*numeric_val) == GNC_ERROR_OK &&
!gnc_numeric_zero_p(*numeric_val))
{
/* Already a valid non-zero result? Then return and don't
* parse the string. Luckily we avoid any locale problems with
* decimal points here! Phew. */
numeric->num = numeric_val->num;
numeric->denom = numeric_val->denom;
return;
}
kvp_val = kvp_frame_get_slot_path(split_kvpf,
GNC_SX_ID,
formula_key,
NULL);
formula_str = kvp_value_get_string(kvp_val);
if (formula_str != NULL && strlen(formula_str) != 0)
{
GHashTable *parser_vars = NULL;
@ -1010,13 +978,17 @@ _get_sx_formula_value(const SchedXaction* sx, const Split *template_split, gnc_n
static void
_get_credit_formula_value(GncSxInstance *instance, const Split *template_split, gnc_numeric *credit_num, GList **creation_errors)
{
_get_sx_formula_value(instance->parent->sx, template_split, credit_num, creation_errors, GNC_SX_CREDIT_FORMULA, GNC_SX_CREDIT_NUMERIC, instance->variable_bindings);
_get_sx_formula_value(instance->parent->sx, template_split, credit_num,
creation_errors, "sx-credit-formula",
"sx-credit-numeric", instance->variable_bindings);
}
static void
_get_debit_formula_value(GncSxInstance *instance, const Split *template_split, gnc_numeric *debit_num, GList **creation_errors)
{
_get_sx_formula_value(instance->parent->sx, template_split, debit_num, creation_errors, GNC_SX_DEBIT_FORMULA, GNC_SX_DEBIT_NUMERIC, instance->variable_bindings);
_get_sx_formula_value(instance->parent->sx, template_split, debit_num,
creation_errors, "sx-debit-formula",
"sx-debit-numeric", instance->variable_bindings);
}
static gboolean
@ -1035,7 +1007,7 @@ create_each_transaction_helper(Transaction *template_txn, void *user_data)
as not finding the approrpiate Accounts and not being able to
parse the formula|credit/debit strings. */
new_txn = xaccTransClone(template_txn);
new_txn = xaccTransCloneNoKvp(template_txn);
xaccTransBeginEdit(new_txn);
g_debug("creating template txn desc [%s] for sx [%s]",
@ -1044,9 +1016,6 @@ create_each_transaction_helper(Transaction *template_txn, void *user_data)
g_debug("template txn currency is %s", gnc_commodity_get_mnemonic(xaccTransGetCurrency (template_txn)));
/* clear any copied KVP data */
qof_instance_set_slots(QOF_INSTANCE(new_txn), kvp_frame_new());
/* Bug#500427: copy the notes, if any */
if (xaccTransGetNotes(template_txn) != NULL)
{
@ -1090,9 +1059,6 @@ create_each_transaction_helper(Transaction *template_txn, void *user_data)
break;
}
/* clear out any copied Split frame data. */
qof_instance_set_slots(QOF_INSTANCE(copying_split), kvp_frame_new());
split_cmdty = xaccAccountGetCommodity(split_acct);
if (first_cmdty == NULL)
{
@ -1215,13 +1181,10 @@ create_each_transaction_helper(Transaction *template_txn, void *user_data)
}
{
kvp_frame *txn_frame;
txn_frame = xaccTransGetSlots(new_txn);
kvp_frame_set_guid(txn_frame, "from-sched-xaction",
xaccSchedXactionGetGUID(creation_data->instance->parent->sx));
/* The transaction was probably marked dirty by xaccTransSetCurrency,
* but just in case: */
qof_instance_set_dirty (QOF_INSTANCE (new_txn));
qof_instance_set (QOF_INSTANCE (new_txn),
"from-sched-xaction",
xaccSchedXactionGetGUID(creation_data->instance->parent->sx),
NULL);
}
xaccTransCommitEdit(new_txn);
@ -1631,9 +1594,14 @@ create_cashflow_helper(Transaction *template_txn, void *user_data)
gint gncn_error;
/* Credit value */
_get_sx_formula_value(creation_data->sx, template_split, &credit_num, creation_data->creation_errors, GNC_SX_CREDIT_FORMULA, GNC_SX_CREDIT_NUMERIC, NULL);
_get_sx_formula_value(creation_data->sx, template_split,
&credit_num, creation_data->creation_errors,
"sx-credit-formula", "sx-credit-numeric",
NULL);
/* Debit value */
_get_sx_formula_value(creation_data->sx, template_split, &debit_num, creation_data->creation_errors, GNC_SX_DEBIT_FORMULA, GNC_SX_DEBIT_NUMERIC, NULL);
_get_sx_formula_value(creation_data->sx, template_split,
&debit_num, creation_data->creation_errors,
"sx-debit-formula", "sx-debit-numeric", NULL);
/* The resulting cash flow number: debit minus credit,
* multiplied with the count factor. */

View File

@ -33,7 +33,7 @@
typedef struct gnc_option GNCOption;
typedef struct gnc_option_section GNCOptionSection;
typedef struct gnc_option_db GNCOptionDB;
/* typedef struct gnc_option_db GNCOptionDB is in qof-book.h */
typedef int GNCOptionDBHandle;

View File

@ -1,3 +1,5 @@
include $(top_srcdir)/test-templates/Makefile.decl
TESTS = \
test-link-module \
test-load-module \
@ -66,3 +68,17 @@ AM_CPPFLAGS = \
-I${top_srcdir}/src/libqof/qof \
${GUILE_CFLAGS} \
${GLIB_CFLAGS}
TEST_PROGS += test-app-utils
noinst_PROGRAMS = ${TEST_PROGS} ${CHECK_PROGS}
test_app_utils_SOURCES = \
test-app-utils.c \
test-option-util.c
test_app_utils_CFLAGS = \
${DEFAULT_INCLUDES} \
-I${top_srcdir}/${MODULEPATH}/ \
-DTESTPROG=test_app_utils \
${GLIB_CFLAGS}

View File

@ -0,0 +1,56 @@
/********************************************************************
* test-app-utils.c: GLib g_test test execution file. *
* Copyright 2013 John Ralls <jralls@ceridwen.us> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
* Boston, MA 02110-1301, USA gnu@gnu.org *
\********************************************************************/
#include <config.h>
#include <glib.h>
#include <qof.h>
#include <libguile.h>
#include <gnc-module.h>
extern void test_suite_option_util (void);
static void
guile_main (void *closure, int argc, char **argv)
{
GNCModule mod;
int retval;
gnc_module_system_init ();
mod = gnc_module_load ("gnucash/app-utils", 0);
test_suite_option_util ();
retval = g_test_run ();
exit (retval);
}
int
main (int argc, char *argv[])
{
qof_init (); /* Initialize the GObject system */
qof_log_init_filename_special ("stderr"); /* Init the log system */
g_test_init (&argc, &argv, NULL); /* initialize test program */
//qof_log_set_level("gnc", G_LOG_LEVEL_DEBUG);
g_test_bug_base("https://bugzilla.gnome.org/show_bug.cgi?id="); /* init the bugzilla URL */
g_setenv ("GNC_UNINSTALLED", "1", TRUE);
scm_boot_guile (argc, argv, guile_main, NULL);
}

View File

@ -0,0 +1,126 @@
/********************************************************************
* test-option-util.c: GLib g_test test suite for Split.c. *
* Copyright 2013 John Ralls <jralls@ceridwen.us> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, you can retrieve it from *
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html *
* or contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
* Boston, MA 02110-1301, USA gnu@gnu.org *
********************************************************************/
#include <config.h>
#include <glib.h>
#include <unittest-support.h>
#include <qofbookslots.h>
#include "../option-util.h"
static const gchar *suitename = "/app-utils/option-util";
void test_suite_option_util (void);
typedef struct
{
QofBook *book;
GSList *hdlrs;
} Fixture;
/* Expose a mostly-private QofInstance function to load options into
* the Book.
*/
extern KvpFrame *qof_instance_get_slots (QofInstance*);
static void
setup (Fixture *fixture, gconstpointer pData)
{
fixture->book = qof_book_new ();
fixture->hdlrs = NULL;
}
static void
setup_kvp (Fixture *fixture, gconstpointer pData)
{
QofBook *book;
KvpFrame *slots;
setup (fixture, pData);
book = fixture->book;
slots = qof_instance_get_slots (QOF_INSTANCE (book));
qof_begin_edit (QOF_INSTANCE (book));
qof_instance_set (QOF_INSTANCE (book),
"trading-accts", "t",
"split-action-num-field", "t",
"autoreadonly-days", (double)21,
NULL);
kvp_frame_set_string (slots, "options/Business/Company Name",
"Bogus Company");
qof_commit_edit (QOF_INSTANCE (book));
}
static void
teardown (Fixture *fixture, gconstpointer pData)
{
qof_book_destroy (fixture->book);
g_slist_free_full (fixture->hdlrs, test_free_log_handler);
test_clear_error_list();
}
static void
test_option_load_from_kvp (Fixture *fixture, gconstpointer pData)
{
QofBook *book = fixture->book;
GNCOptionDB *odb = gnc_option_db_new_for_type (QOF_ID_BOOK);
qof_book_load_options (book, gnc_option_db_load_from_kvp, odb);
g_assert (gnc_option_db_lookup_boolean_option (odb, OPTION_SECTION_ACCOUNTS,
OPTION_NAME_TRADING_ACCOUNTS, FALSE));
g_assert_cmpstr (gnc_option_db_lookup_string_option (odb, "Business", "Company Name", FALSE), ==, "Bogus Company");
g_assert_cmpfloat (gnc_option_db_lookup_number_option (odb, OPTION_SECTION_ACCOUNTS, OPTION_NAME_AUTO_READONLY_DAYS, FALSE), ==, 21);
gnc_option_db_destroy (odb);
}
static void
test_option_save_to_kvp (Fixture *fixture, gconstpointer pData)
{
QofBook *book = fixture->book;
GNCOptionDB *odb = gnc_option_db_new_for_type (QOF_ID_BOOK);
KvpFrame *slots = qof_instance_get_slots (QOF_INSTANCE (book));
g_assert (gnc_option_db_set_boolean_option (odb, OPTION_SECTION_ACCOUNTS,
OPTION_NAME_TRADING_ACCOUNTS,
TRUE));
g_assert (gnc_option_db_set_string_option (odb, "Business", "Company Name",
"Bogus Company"));
g_assert (gnc_option_db_set_number_option (odb, OPTION_SECTION_ACCOUNTS,
OPTION_NAME_AUTO_READONLY_DAYS,
17));
qof_book_save_options (book, gnc_option_db_save_to_kvp, odb, TRUE);
g_assert_cmpstr (kvp_frame_get_string (slots, "options/Accounts/Use Trading Accounts"), == , "t");
g_assert_cmpstr (kvp_frame_get_string (slots, "options/Business/Company Name"), ==, "Bogus Company");
g_assert_cmpfloat (kvp_frame_get_double (slots, "options/Accounts/Day Threshold for Read-Only Transactions (red line)"), ==, 17);
gnc_option_db_destroy (odb);
}
void
test_suite_option_util (void)
{
GNC_TEST_ADD (suitename, "Option DB Load from KVP", Fixture, NULL, setup_kvp, test_option_load_from_kvp, teardown);
GNC_TEST_ADD (suitename, "Option DB Save to KVP", Fixture, NULL, setup, test_option_save_to_kvp, teardown);
}

View File

@ -168,6 +168,9 @@ compare_sxs( QofBook* book_1, QofBook* book_2 )
compare_single_sx, "Scheduled transaction lists match" );
}
/* EFFECTIVE FRIEND FUNCTION */
extern KvpFrame *qof_instance_get_slots (const QofInstance *);
static void
compare_single_lot( QofInstance* inst, gpointer user_data )
{
@ -181,8 +184,8 @@ compare_single_lot( QofInstance* inst, gpointer user_data )
gnc_lot_get_account (lot_2), FALSE ));
g_assert_cmpint (gnc_lot_is_closed (lot_1), ==, gnc_lot_is_closed (lot_2));
g_assert (kvp_frame_compare (gnc_lot_get_slots (lot_1),
gnc_lot_get_slots (lot_2)) == 0);
g_assert (kvp_frame_compare (qof_instance_get_slots (QOF_INSTANCE (lot_1)),
qof_instance_get_slots (QOF_INSTANCE (lot_2))) == 0);
splits1 = gnc_lot_get_split_list (lot_1);
splits2 = gnc_lot_get_split_list (lot_2);
g_assert_cmpint (g_list_length (splits1), ==, g_list_length (splits2));

View File

@ -294,12 +294,14 @@ load_all_accounts( GncSqlBackend* be )
{
acct_balances_t* balances = (acct_balances_t*)bal->data;
qof_instance_increase_editlevel (balances->acct);
g_object_set( balances->acct,
"start-balance", &balances->balance,
"start-cleared-balance", &balances->cleared_balance,
"start-reconciled-balance", &balances->reconciled_balance,
NULL);
qof_instance_decrease_editlevel (balances->acct);
}
if ( bal_slist != NULL )
{
@ -418,7 +420,9 @@ load_account_guid( const GncSqlBackend* be, GncSqlRow* row,
{
if ( table_row->gobj_param_name != NULL )
{
qof_instance_increase_editlevel (pObject);
g_object_set( pObject, table_row->gobj_param_name, account, NULL );
qof_instance_decrease_editlevel (pObject);
}
else
{

View File

@ -115,7 +115,9 @@ load_address( const GncSqlBackend* be, GncSqlRow* row,
}
if ( table_row->gobj_param_name != NULL )
{
qof_instance_increase_editlevel (pObject);
g_object_set( pObject, table_row->gobj_param_name, addr, NULL );
qof_instance_decrease_editlevel (pObject);
}
else
{

View File

@ -1204,7 +1204,11 @@ const GncSqlColumnTableEntry* table_row )
s = g_value_get_string( val );
if ( table_row->gobj_param_name != NULL )
{
if (QOF_IS_INSTANCE (pObject))
qof_instance_increase_editlevel (QOF_INSTANCE (pObject));
g_object_set( pObject, table_row->gobj_param_name, s, NULL );
if (QOF_IS_INSTANCE (pObject))
qof_instance_decrease_editlevel (QOF_INSTANCE (pObject));
}
else
{
@ -1308,7 +1312,11 @@ load_int( const GncSqlBackend* be, GncSqlRow* row,
}
if ( table_row->gobj_param_name != NULL )
{
if (QOF_IS_INSTANCE (pObject))
qof_instance_increase_editlevel (QOF_INSTANCE (pObject));
g_object_set( pObject, table_row->gobj_param_name, int_value, NULL );
if (QOF_IS_INSTANCE (pObject))
qof_instance_decrease_editlevel (QOF_INSTANCE (pObject));
}
else
{
@ -1406,7 +1414,11 @@ load_boolean( const GncSqlBackend* be, GncSqlRow* row,
}
if ( table_row->gobj_param_name != NULL )
{
if (QOF_IS_INSTANCE (pObject))
qof_instance_increase_editlevel (QOF_INSTANCE (pObject));
g_object_set( pObject, table_row->gobj_param_name, int_value, NULL );
if (QOF_IS_INSTANCE (pObject))
qof_instance_decrease_editlevel (QOF_INSTANCE (pObject));
}
else
{
@ -1499,7 +1511,11 @@ load_int64( const GncSqlBackend* be, GncSqlRow* row,
}
if ( table_row->gobj_param_name != NULL )
{
if (QOF_IS_INSTANCE (pObject))
qof_instance_increase_editlevel (QOF_INSTANCE (pObject));
g_object_set( pObject, table_row->gobj_param_name, i64_value, NULL );
if (QOF_IS_INSTANCE (pObject))
qof_instance_decrease_editlevel (QOF_INSTANCE (pObject));
}
else
{
@ -1606,7 +1622,11 @@ load_double( const GncSqlBackend* be, GncSqlRow* row,
}
if ( table_row->gobj_param_name != NULL )
{
if (QOF_IS_INSTANCE (pObject))
qof_instance_increase_editlevel (QOF_INSTANCE (pObject));
g_object_set( pObject, table_row->gobj_param_name, d_value, NULL );
if (QOF_IS_INSTANCE (pObject))
qof_instance_decrease_editlevel (QOF_INSTANCE (pObject));
}
else
{
@ -1705,7 +1725,11 @@ load_guid( const GncSqlBackend* be, GncSqlRow* row,
{
if ( table_row->gobj_param_name != NULL )
{
if (QOF_IS_INSTANCE (pObject))
qof_instance_increase_editlevel (QOF_INSTANCE (pObject));
g_object_set( pObject, table_row->gobj_param_name, pGuid, NULL );
if (QOF_IS_INSTANCE (pObject))
qof_instance_decrease_editlevel (QOF_INSTANCE (pObject));
}
else
{
@ -1912,7 +1936,11 @@ load_timespec( const GncSqlBackend* be, GncSqlRow* row,
{
if (table_row->gobj_param_name != NULL)
{
if (QOF_IS_INSTANCE (pObject))
qof_instance_increase_editlevel (QOF_INSTANCE (pObject));
g_object_set( pObject, table_row->gobj_param_name, &ts, NULL );
if (QOF_IS_INSTANCE (pObject))
qof_instance_decrease_editlevel (QOF_INSTANCE (pObject));
}
else
{
@ -2014,7 +2042,11 @@ load_date( const GncSqlBackend* be, GncSqlRow* row,
g_date_time_unref (gdt);
if ( table_row->gobj_param_name != NULL )
{
if (QOF_IS_INSTANCE (pObject))
qof_instance_increase_editlevel (QOF_INSTANCE (pObject));
g_object_set( pObject, table_row->gobj_param_name, date, NULL );
if (QOF_IS_INSTANCE (pObject))
qof_instance_increase_editlevel (QOF_INSTANCE (pObject));
}
else
{
@ -2048,7 +2080,12 @@ load_date( const GncSqlBackend* be, GncSqlRow* row,
date = g_date_new_dmy( day, month, year );
if ( table_row->gobj_param_name != NULL )
{
g_object_set( pObject, table_row->gobj_param_name, date, NULL );
if (QOF_IS_INSTANCE (pObject))
qof_instance_increase_editlevel (QOF_INSTANCE (pObject));
g_object_set (pObject, table_row->gobj_param_name,
date, NULL);
if (QOF_IS_INSTANCE (pObject))
qof_instance_increase_editlevel (QOF_INSTANCE (pObject));
}
else
{
@ -2187,7 +2224,11 @@ load_numeric( const GncSqlBackend* be, GncSqlRow* row,
{
if ( table_row->gobj_param_name != NULL )
{
if (QOF_IS_INSTANCE (pObject))
qof_instance_increase_editlevel (QOF_INSTANCE (pObject));
g_object_set( pObject, table_row->gobj_param_name, &n, NULL );
if (QOF_IS_INSTANCE (pObject))
qof_instance_increase_editlevel (QOF_INSTANCE (pObject));
}
else
{

View File

@ -363,7 +363,9 @@ load_billterm_guid( const GncSqlBackend* be, GncSqlRow* row,
{
if ( table_row->gobj_param_name != NULL )
{
qof_instance_increase_editlevel (pObject);
g_object_set( pObject, table_row->gobj_param_name, term, NULL );
qof_instance_decrease_editlevel (pObject);
}
else
{

View File

@ -500,7 +500,9 @@ load_budget_guid( const GncSqlBackend* be, GncSqlRow* row,
{
if ( table_row->gobj_param_name != NULL )
{
qof_instance_increase_editlevel (pObject);
g_object_set( pObject, table_row->gobj_param_name, budget, NULL );
qof_instance_decrease_editlevel (pObject);
}
else
{

View File

@ -283,7 +283,9 @@ load_commodity_guid( const GncSqlBackend* be, GncSqlRow* row,
{
if ( table_row->gobj_param_name != NULL )
{
qof_instance_increase_editlevel (pObject);
g_object_set( pObject, table_row->gobj_param_name, commodity, NULL );
qof_instance_decrease_editlevel (pObject);
}
else if ( setter != NULL )
{

View File

@ -303,7 +303,9 @@ load_invoice_guid( const GncSqlBackend* be, GncSqlRow* row,
{
if ( table_row->gobj_param_name != NULL )
{
qof_instance_increase_editlevel (pObject);
g_object_set( pObject, table_row->gobj_param_name, invoice, NULL );
qof_instance_decrease_editlevel (pObject);
}
else
{

View File

@ -235,7 +235,9 @@ load_lot_guid( const GncSqlBackend* be, GncSqlRow* row,
{
if ( table_row->gobj_param_name != NULL )
{
qof_instance_increase_editlevel (pObject);
g_object_set( pObject, table_row->gobj_param_name, lot, NULL );
qof_instance_decrease_editlevel (pObject);
}
else
{

View File

@ -220,7 +220,9 @@ load_order_guid( const GncSqlBackend* be, GncSqlRow* row,
{
if ( table_row->gobj_param_name != NULL )
{
qof_instance_increase_editlevel (pObject);
g_object_set( pObject, table_row->gobj_param_name, order, NULL );
qof_instance_decrease_editlevel (pObject);
}
else
{

View File

@ -156,7 +156,9 @@ load_owner( const GncSqlBackend* be, GncSqlRow* row,
if ( table_row->gobj_param_name != NULL )
{
qof_instance_increase_editlevel (pObject);
g_object_set( pObject, table_row->gobj_param_name, &owner, NULL );
qof_instance_decrease_editlevel (pObject);
}
else
{

View File

@ -523,7 +523,9 @@ load_taxtable_guid( const GncSqlBackend* be, GncSqlRow* row,
{
if ( table_row->gobj_param_name != NULL )
{
qof_instance_increase_editlevel (pObject);
g_object_set( pObject, table_row->gobj_param_name, taxtable, NULL );
qof_instance_decrease_editlevel (pObject);
}
else
{

View File

@ -415,6 +415,7 @@ query_transactions( GncSqlBackend* be, GncSqlStatement* stmt )
"end-reconciled-balance", &pnew_end_r_bal,
NULL );
qof_instance_increase_editlevel (balns-acc);
if ( !gnc_numeric_eq( *pnew_end_bal, balns->end_bal ) )
{
adj = gnc_numeric_sub( balns->end_bal, *pnew_end_bal,
@ -422,6 +423,7 @@ query_transactions( GncSqlBackend* be, GncSqlStatement* stmt )
balns->start_bal = gnc_numeric_add( balns->start_bal, adj,
GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
g_object_set( balns->acc, "start-balance", &balns->start_bal, NULL );
qof_instance_decrease_editlevel (balns-acc);
}
if ( !gnc_numeric_eq( *pnew_end_c_bal, balns->end_cleared_bal ) )
{
@ -439,6 +441,7 @@ query_transactions( GncSqlBackend* be, GncSqlStatement* stmt )
GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD );
g_object_set( balns->acc, "start-reconciled-balance", &balns->start_reconciled_bal, NULL );
}
qof_instance_decrease_editlevel (balns-acc);
xaccAccountRecomputeBalance( balns->acc );
g_free( pnew_end_bal );
g_free( pnew_end_c_bal );
@ -1461,7 +1464,9 @@ load_tx_guid( const GncSqlBackend* be, GncSqlRow* row,
{
if ( table_row->gobj_param_name != NULL )
{
qof_instance_increase_editlevel (pObject);
g_object_set( pObject, table_row->gobj_param_name, tx, NULL );
qof_instance_decrease_editlevel (pObject);
}
else
{

View File

@ -71,6 +71,9 @@ const gchar *account_version_string = "2.0.0";
#define act_hidden_string "act:hidden"
#define act_placeholder_string "act:placeholder"
/* EFFECTIVE FRIEND FUNCTION */
extern KvpFrame *qof_instance_get_slots (const QofInstance *);
xmlNodePtr
gnc_account_dom_tree_create(Account *act,
gboolean exporting,
@ -134,7 +137,7 @@ gnc_account_dom_tree_create(Account *act,
xmlAddChild(ret, text_to_dom_tree(act_description_string, str));
}
kf = xaccAccountGetSlots(act);
kf = qof_instance_get_slots (QOF_INSTANCE (act));
if (kf)
{
xmlNodePtr kvpnode = kvp_frame_to_dom_tree(act_slots_string, kf);
@ -370,7 +373,7 @@ account_slots_handler (xmlNodePtr node, gpointer act_pdata)
struct account_pdata *pdata = act_pdata;
return dom_tree_to_kvp_frame_given
(node, xaccAccountGetSlots (pdata->account));
(node, qof_instance_get_slots (QOF_INSTANCE (pdata->account)));
}
static gboolean

View File

@ -109,10 +109,10 @@ gnc_book_dom_tree_create(QofBook *book)
xmlAddChild(ret, guid_to_dom_tree(book_id_string,
qof_book_get_guid(book)));
if (qof_book_get_slots(book))
if (qof_instance_get_slots (QOF_INSTANCE (book)))
{
xmlNodePtr kvpnode = kvp_frame_to_dom_tree(book_slots_string,
qof_book_get_slots(book));
qof_instance_get_slots (QOF_INSTANCE (book)));
if (kvpnode)
xmlAddChild(ret, kvpnode);
}
@ -162,10 +162,10 @@ write_book_parts(FILE *out, QofBook *book)
if (ferror(out) || fprintf(out, "\n") < 0)
return FALSE;
if (qof_book_get_slots(book))
if (qof_instance_get_slots (QOF_INSTANCE (book)))
{
xmlNodePtr kvpnode = kvp_frame_to_dom_tree(book_slots_string,
qof_book_get_slots(book));
qof_instance_get_slots (QOF_INSTANCE (book)));
if (kvpnode)
{
xmlElemDump(out, NULL, kvpnode);
@ -203,7 +203,7 @@ book_slots_handler (xmlNodePtr node, gpointer book_pdata)
/* the below works only because the get is gaurenteed to return
* a frame, even if its empty */
success = dom_tree_to_kvp_frame_given (node, qof_book_get_slots (book));
success = dom_tree_to_kvp_frame_given (node, qof_instance_get_slots (QOF_INSTANCE (book)));
g_return_val_if_fail(success, FALSE);

View File

@ -72,6 +72,9 @@ const gchar *invoice_version_string = "2.0.0";
#define invoice_tochargeamt_string "invoice:charge-amt"
#define invoice_slots_string "invoice:slots"
/* EFFECTIVE FRIEND FUNCTION */
extern KvpFrame *qof_instance_get_slots (const QofInstance *);
static void
maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
{
@ -410,7 +413,7 @@ invoice_slots_handler (xmlNodePtr node, gpointer invoice_pdata)
struct invoice_pdata *pdata = invoice_pdata;
return dom_tree_to_kvp_frame_given
(node, xaccAccountGetSlots (pdata->invoice));
(node, qof_instance_get_slots (QOF_INSTANCE (pdata->invoice)));
}
static struct dom_tree_handler invoice_handlers_v2[] =

View File

@ -53,6 +53,8 @@ const gchar *lot_version_string = "2.0.0";
#define gnc_lot_string "gnc:lot"
#define lot_id_string "lot:id"
#define lot_slots_string "lot:slots"
/* EFFECTIVE FRIEND FUNCTION */
extern KvpFrame *qof_instance_get_slots (const QofInstance *);
xmlNodePtr
gnc_lot_dom_tree_create(GNCLot *lot)
@ -66,7 +68,7 @@ gnc_lot_dom_tree_create(GNCLot *lot)
xmlAddChild(ret, guid_to_dom_tree(lot_id_string, gnc_lot_get_guid(lot)));
kf = gnc_lot_get_slots (lot);
kf = qof_instance_get_slots (QOF_INSTANCE (lot));
if (kf)
{
xmlNodePtr kvpnode = kvp_frame_to_dom_tree(lot_slots_string, kf);
@ -112,7 +114,7 @@ lot_slots_handler (xmlNodePtr node, gpointer p)
ENTER("(lot=%p)", pdata->lot);
success = dom_tree_to_kvp_frame_given
(node, gnc_lot_get_slots (pdata->lot));
(node, qof_instance_get_slots (QOF_INSTANCE (pdata->lot)));
LEAVE("");
g_return_val_if_fail(success, FALSE);

View File

@ -49,6 +49,9 @@
const gchar *transaction_version_string = "2.0.0";
/* EFFECTIVE FRIEND FUNCTION */
extern KvpFrame *qof_instance_get_slots (const QofInstance *);
static void
add_gnc_num(xmlNodePtr node, const gchar *tag, gnc_numeric num)
{
@ -129,7 +132,7 @@ split_to_dom_tree(const gchar *tag, Split *spl)
}
{
xmlNodePtr kvpnode = kvp_frame_to_dom_tree("split:slots",
xaccSplitGetSlots(spl));
qof_instance_get_slots (QOF_INSTANCE (spl)));
if (kvpnode)
{
xmlAddChild(ret, kvpnode);
@ -192,7 +195,7 @@ gnc_transaction_dom_tree_create(Transaction *trn)
{
xmlNodePtr kvpnode = kvp_frame_to_dom_tree("trn:slots",
xaccTransGetSlots(trn));
qof_instance_get_slots (QOF_INSTANCE (trn)));
if (kvpnode)
{
xmlAddChild(ret, kvpnode);
@ -368,7 +371,7 @@ spl_slots_handler(xmlNodePtr node, gpointer data)
gboolean successful;
successful = dom_tree_to_kvp_frame_given(node,
xaccSplitGetSlots (pdata->split));
qof_instance_get_slots (QOF_INSTANCE (pdata->split)));
g_return_val_if_fail(successful, FALSE);
return TRUE;
@ -527,7 +530,7 @@ trn_slots_handler(xmlNodePtr node, gpointer trans_pdata)
Transaction *trn = pdata->trans;
gboolean successful;
successful = dom_tree_to_kvp_frame_given(node, xaccTransGetSlots(trn));
successful = dom_tree_to_kvp_frame_given(node, qof_instance_get_slots (QOF_INSTANCE (trn)));
g_return_val_if_fail(successful, FALSE);

View File

@ -2182,7 +2182,7 @@ gnc_xml2_parse_with_subst (FileBackend *fbe, QofBook *book, GHashTable *subst)
push_data, GNC_BOOK_XML2_FILE);
if (success)
qof_book_kvp_changed(book);
qof_instance_set_dirty (QOF_INSTANCE (book));
return success;
}

View File

@ -144,7 +144,7 @@ node_and_account_equal(xmlNodePtr node, Account *act)
{
/* xaccAccountDeleteOldData (act); */
if (!equals_node_val_vs_kvp_frame(mark, xaccAccountGetSlots(act)))
if (!equals_node_val_vs_kvp_frame(mark, qof_instance_get_slots(QOF_INSTANCE (act))))
{
return g_strdup("slots differ");
}

View File

@ -306,7 +306,7 @@ node_and_transaction_equal(xmlNodePtr node, Transaction *trn)
}
else if (g_strcmp0((char*)mark->name, "trn:slots") == 0)
{
if (!equals_node_val_vs_kvp_frame(mark, xaccTransGetSlots(trn)))
if (!equals_node_val_vs_kvp_frame(mark, qof_instance_get_slots (QOF_INSTANCE (trn))))
{
return "slots differ";
}

View File

@ -90,8 +90,6 @@
#define GNC_PREF_ACCUM_SPLITS "accumulate-splits"
#define GNC_PREF_DAYS_IN_ADVANCE "days-in-advance"
#define LAST_POSTED_TO_ACCT "last-posted-to-acct"
void gnc_invoice_window_ok_cb (GtkWidget *widget, gpointer data);
void gnc_invoice_window_cancel_cb (GtkWidget *widget, gpointer data);
void gnc_invoice_window_help_cb (GtkWidget *widget, gpointer data);
@ -681,7 +679,6 @@ gnc_dialog_post_invoice(InvoiceWindow *iw, char *message,
GList * acct_types = NULL;
GList * acct_commodities = NULL;
QofInstance *owner_inst;
KvpFrame *kvpf;
EntryList *entries, *entries_iter;
invoice = iw_get_invoice (iw);
@ -726,12 +723,14 @@ gnc_dialog_post_invoice(InvoiceWindow *iw, char *message,
/* Get the due date and posted account */
*ddue = *postdate;
*memo = NULL;
owner_inst = qofOwnerGetOwner (gncOwnerGetEndOwner (&(iw->owner)));
kvpf = qof_instance_get_slots (owner_inst);
*acc = xaccAccountLookup (kvp_frame_get_guid (kvpf, LAST_POSTED_TO_ACCT),
iw->book);
{
GncGUID *guid = NULL;
owner_inst = qofOwnerGetOwner (gncOwnerGetEndOwner (&(iw->owner)));
qof_instance_get (owner_inst,
"invoice-last-posted-account", &guid,
NULL);
*acc = xaccAccountLookup (guid, iw->book);
}
/* Get the default for the accumulate option */
*accumulate = gnc_prefs_get_bool(GNC_PREFS_GROUP_INVOICE, GNC_PREF_ACCUM_SPLITS);
@ -762,8 +761,6 @@ gnc_invoice_post(InvoiceWindow *iw, struct post_invoice_params *post_params)
Timespec ddue, postdate;
gboolean accumulate;
QofInstance *owner_inst;
KvpFrame *kvpf;
KvpValue *kvp_val;
const char *text;
GHashTable *foreign_currs;
GHashTableIter foreign_currs_iter;
@ -911,14 +908,18 @@ gnc_invoice_post(InvoiceWindow *iw, struct post_invoice_params *post_params)
}
/* Save account as last used account in the kvp frame of the invoice owner */
/* Save account as last used account in the owner's
* invoice-last-posted-account property.
*/
owner_inst = qofOwnerGetOwner (gncOwnerGetEndOwner (&(iw->owner)));
kvpf = qof_instance_get_slots (owner_inst);
kvp_val = kvp_value_new_guid (qof_instance_get_guid (QOF_INSTANCE (acc)));;
qof_begin_edit (owner_inst);
kvp_frame_set_slot_nc (kvpf, LAST_POSTED_TO_ACCT, kvp_val);
qof_instance_set_dirty (owner_inst);
qof_commit_edit (owner_inst);
{
const GncGUID *guid = qof_instance_get_guid (QOF_INSTANCE (acc));
qof_begin_edit (owner_inst);
qof_instance_set (owner_inst,
"invoice-last-posted-account", guid,
NULL);
qof_commit_edit (owner_inst);
}
/* ... post it ... */
if (is_cust_doc)

View File

@ -452,23 +452,15 @@ gnc_payment_dialog_owner_changed (PaymentWindow *pw)
{
Account *last_acct = NULL;
GncGUID *guid = NULL;
KvpValue* value;
KvpFrame* slots;
GncOwner *owner = &pw->owner;
/* If the owner changed, the initial invoice is no longer valid */
pw->invoice = NULL;
/* Now handle the account tree */
slots = gncOwnerGetSlots(owner);
if (slots)
{
value = kvp_frame_get_slot_path(slots, "payment", "last_acct", NULL);
if (value)
{
guid = kvp_value_get_guid(value);
}
}
qof_instance_get (QOF_INSTANCE (owner),
"payment-last-account", &guid,
NULL);
/* refresh the post and acc available accounts, but cleanup first */
if (pw->acct_types)
@ -514,20 +506,17 @@ gnc_payment_dialog_post_to_changed (PaymentWindow *pw)
static void
gnc_payment_dialog_remember_account (PaymentWindow *pw, Account *acc)
{
KvpValue* value;
KvpFrame* slots = gncOwnerGetSlots(&pw->owner);
GncOwner *owner = &pw->owner;
const GncGUID *guid;
if (!acc) return;
if (!slots) return;
value = kvp_value_new_guid(xaccAccountGetGUID(acc));
if (!value) return;
xaccAccountBeginEdit (acc);
kvp_frame_set_slot_path(slots, value, "payment", "last_acct", NULL);
qof_instance_set_dirty (QOF_INSTANCE (acc));
xaccAccountCommitEdit (acc);
kvp_value_delete(value);
guid = xaccAccountGetGUID(acc);
qof_begin_edit (QOF_INSTANCE (owner));
qof_instance_set (QOF_INSTANCE (owner),
"payment-last-account", guid,
NULL);
qof_commit_edit (QOF_INSTANCE (owner));
}

View File

@ -67,10 +67,12 @@ static void gnc_features_init ()
g_strdup (known_features[i].desc));
}
static void gnc_features_test_one(const gchar *key, KvpValue *value, gpointer data)
static void gnc_features_test_one(gpointer pkey, gpointer value,
gpointer data)
{
const gchar *key = (const gchar*)pkey;
const gchar *feature_desc = (const gchar*)value;
GList **unknown_features;
gchar *feature_desc;
g_assert(data);
unknown_features = (GList**) data;
@ -80,54 +82,47 @@ static void gnc_features_test_one(const gchar *key, KvpValue *value, gpointer da
return;
/* It is unknown, so add the description to the unknown features list: */
feature_desc = kvp_value_get_string(value);
g_assert(feature_desc);
*unknown_features = g_list_prepend(*unknown_features, feature_desc);
*unknown_features = g_list_prepend(*unknown_features,
(gpointer)feature_desc);
}
/* Check if the session requires features unknown to this version of GnuCash.
*
* Returns a message to display if we found unknown features, NULL if we're okay.
* Returns a message to display if we found unknown features, NULL if
* we're okay.
*/
gchar *gnc_features_test_unknown (QofBook *book)
{
KvpFrame *frame = qof_book_get_slots (book);
KvpValue *value;
/* Setup the known_features hash table */
gnc_features_init();
g_assert(frame);
value = kvp_frame_get_value(frame, "features");
GList* features_list = NULL;
GHashTable *features_used = qof_book_get_features (book);
if (value)
/* Iterate over the members of this frame for unknown features */
g_hash_table_foreach (features_used, &gnc_features_test_one,
&features_list);
if (features_list)
{
GList* features_list = NULL;
frame = kvp_value_get_frame(value);
g_assert(frame);
/* Iterate over the members of this frame for unknown features */
kvp_frame_for_each_slot(frame, &gnc_features_test_one, &features_list);
if (features_list)
{
GList *i;
char* msg = g_strdup(
_("This Dataset contains features not supported by this "
"version of GnuCash. You must use a newer version of "
"GnuCash in order to support the following features:"
GList *i;
char* msg = g_strdup(_("This Dataset contains features not supported "
"by this version of GnuCash. You must use a "
"newer version of GnuCash in order to support "
"the following features:"
));
for (i = features_list; i; i = i->next)
{
char *tmp = g_strconcat(msg, "\n* ", i->data, NULL);
g_free (msg);
msg = tmp;
}
for (i = features_list; i; i = i->next)
{
char *tmp = g_strconcat(msg, "\n* ", i->data, NULL);
g_free (msg);
msg = tmp;
}
g_list_free(features_list);
return msg;
}
g_list_free(features_list);
return msg;
}
return NULL;
@ -135,9 +130,7 @@ gchar *gnc_features_test_unknown (QofBook *book)
void gnc_features_set_used (QofBook *book, const gchar *feature)
{
KvpFrame *frame;
const gchar *description;
gchar *kvp_path;
g_return_if_fail (book);
g_return_if_fail (feature);
@ -152,10 +145,7 @@ void gnc_features_set_used (QofBook *book, const gchar *feature)
return;
}
frame = qof_book_get_slots (book);
kvp_path = g_strconcat ("/features/", feature, NULL);
kvp_frame_set_string (frame, kvp_path, description);
qof_book_kvp_changed (book);
qof_book_set_feature (book, feature, description);
}

View File

@ -38,12 +38,20 @@
#include "gnc-glib-utils.h"
#include "gnc-lot.h"
#include "gnc-pricedb.h"
#include "qofinstance-p.h"
static QofLogModule log_module = GNC_MOD_ACCOUNT;
/* The Canonical Account Separator. Pre-Initialized. */
static gchar account_separator[8] = ".";
static gunichar account_uc_separator = ':';
/* Predefined KVP paths */
static const char *KEY_ASSOC_INCOME_ACCOUNT = "ofx/associated-income-account";
#define AB_KEY "hbci"
#define AB_ACCOUNT_ID "account-id"
#define AB_ACCOUNT_UID "account-uid"
#define AB_BANK_CODE "bank-code"
#define AB_TRANS_RETRIEVAL "trans-retrieval"
enum
{
@ -53,37 +61,48 @@ enum
enum
{
PROP_0,
PROP_NAME,
PROP_FULL_NAME,
PROP_CODE,
PROP_DESCRIPTION,
PROP_COLOR,
PROP_NOTES,
PROP_TYPE,
PROP_NAME, /* Table */
PROP_FULL_NAME, /* Constructed */
PROP_CODE, /* Table */
PROP_DESCRIPTION, /* Table */
PROP_COLOR, /* KVP */
PROP_NOTES, /* KVP */
PROP_TYPE, /* Table */
PROP_COMMODITY,
PROP_COMMODITY_SCU,
PROP_NON_STD_SCU,
PROP_SORT_DIRTY,
PROP_BALANCE_DIRTY,
PROP_START_BALANCE,
PROP_START_CLEARED_BALANCE,
PROP_START_RECONCILED_BALANCE,
PROP_END_BALANCE,
PROP_END_CLEARED_BALANCE,
PROP_END_RECONCILED_BALANCE,
// PROP_PARENT, /* Table, Not a property */
PROP_COMMODITY, /* Table */
PROP_COMMODITY_SCU, /* Table */
PROP_NON_STD_SCU, /* Table */
PROP_END_BALANCE, /* Constructed */
PROP_END_CLEARED_BALANCE, /* Constructed */
PROP_END_RECONCILED_BALANCE, /* Constructed */
PROP_POLICY,
PROP_MARK,
PROP_TAX_RELATED,
PROP_TAX_CODE,
PROP_TAX_SOURCE,
PROP_TAX_COPY_NUMBER,
PROP_TAX_RELATED, /* KVP */
PROP_TAX_CODE, /* KVP */
PROP_TAX_SOURCE, /* KVP */
PROP_TAX_COPY_NUMBER, /* KVP */
PROP_HIDDEN,
PROP_PLACEHOLDER,
PROP_FILTER,
PROP_SORT_ORDER,
PROP_HIDDEN, /* Table slot exists, but in KVP in memory & xml */
PROP_PLACEHOLDER, /* Table slot exists, but in KVP in memory & xml */
PROP_FILTER, /* KVP */
PROP_SORT_ORDER, /* KVP */
PROP_LOT_NEXT_ID, /* KVP */
PROP_ONLINE_ACCOUNT, /* KVP */
PROP_OFX_INCOME_ACCOUNT, /* KVP */
PROP_AB_ACCOUNT_ID, /* KVP */
PROP_AB_ACCOUNT_UID, /* KVP */
PROP_AB_BANK_CODE, /* KVP */
PROP_AB_TRANS_RETRIEVAL, /* KVP */
PROP_RUNTIME_0,
PROP_POLICY, /* Cached Value */
PROP_MARK, /* Runtime Value */
PROP_SORT_DIRTY, /* Runtime Value */
PROP_BALANCE_DIRTY, /* Runtime Value */
PROP_START_BALANCE, /* Runtime Value */
PROP_START_CLEARED_BALANCE, /* Runtime Value */
PROP_START_RECONCILED_BALANCE, /* Runtime Value */
};
#define GET_PRIVATE(o) \
@ -282,6 +301,8 @@ gnc_account_get_property (GObject *object,
{
Account *account;
AccountPrivate *priv;
const gchar *key;
GValue *temp;
g_return_if_fail(GNC_IS_ACCOUNT(object));
@ -377,6 +398,36 @@ gnc_account_get_property (GObject *object,
case PROP_SORT_ORDER:
g_value_set_string(value, xaccAccountGetSortOrder(account));
break;
case PROP_LOT_NEXT_ID:
key = "lot-mgmt/next-id";
/* Pre-set the value in case the frame is empty */
g_value_set_int64 (value, 0);
qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
break;
case PROP_ONLINE_ACCOUNT:
key = "online_id";
qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
break;
case PROP_OFX_INCOME_ACCOUNT:
key = KEY_ASSOC_INCOME_ACCOUNT;
qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
break;
case PROP_AB_ACCOUNT_ID:
key = AB_KEY "/" AB_ACCOUNT_ID;
qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
break;
case PROP_AB_ACCOUNT_UID:
key = AB_KEY "/" AB_ACCOUNT_UID;
qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
break;
case PROP_AB_BANK_CODE:
key = AB_KEY "/" AB_BANK_CODE;
qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
break;
case PROP_AB_TRANS_RETRIEVAL:
key = AB_KEY "/" AB_TRANS_RETRIEVAL;
qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -391,10 +442,13 @@ gnc_account_set_property (GObject *object,
{
Account *account;
gnc_numeric *number;
const gchar *key = NULL;
g_return_if_fail(GNC_IS_ACCOUNT(object));
account = GNC_ACCOUNT(object);
if (prop_id < PROP_RUNTIME_0)
g_assert (qof_instance_get_editlevel(account));
switch (prop_id)
{
@ -476,6 +530,34 @@ gnc_account_set_property (GObject *object,
case PROP_SORT_ORDER:
xaccAccountSetSortOrder(account, g_value_get_string(value));
break;
case PROP_LOT_NEXT_ID:
key = "lot-mgmt/next-id";
qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
break;
case PROP_ONLINE_ACCOUNT:
key = "online_id";
qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
break;
case PROP_OFX_INCOME_ACCOUNT:
key = KEY_ASSOC_INCOME_ACCOUNT;
qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
break;
case PROP_AB_ACCOUNT_ID:
key = AB_KEY "/" AB_ACCOUNT_ID;
qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
break;
case PROP_AB_ACCOUNT_UID:
key = AB_KEY "/" AB_ACCOUNT_UID;
qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
break;
case PROP_AB_BANK_CODE:
key = AB_KEY "/" AB_BANK_CODE;
qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
break;
case PROP_AB_TRANS_RETRIEVAL:
key = AB_KEY "/" AB_TRANS_RETRIEVAL;
qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -833,6 +915,77 @@ gnc_account_class_init (AccountClass *klass)
"the sort order to be recalled.",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_LOT_NEXT_ID,
g_param_spec_int64 ("lot-next-id",
"Lot Next ID",
"Tracks the next id to use in gnc_lot_make_default.",
(gint64)1,
G_MAXINT64,
(gint64)1,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_ONLINE_ACCOUNT,
g_param_spec_string ("online-id",
"Online Account ID",
"The online account which corresponds to this "
"account for OFX import",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property(
gobject_class,
PROP_OFX_INCOME_ACCOUNT,
g_param_spec_boxed("ofx-income-account",
"Associated income account",
"Used by the OFX importer.",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_AB_ACCOUNT_ID,
g_param_spec_string ("ab-account-id",
"AQBanking Account ID",
"The AqBanking account which corresponds to this "
"account for AQBanking import",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_AB_BANK_CODE,
g_param_spec_string ("ab-bank-code",
"AQBanking Bank Code",
"The online account which corresponds to this "
"account for AQBanking import",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_AB_ACCOUNT_UID,
g_param_spec_int64 ("ab-account-uid",
"AQBanking Account UID",
"Tracks the next id to use in gnc_lot_make_default.",
(gint64)1,
G_MAXINT64,
(gint64)1,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_AB_TRANS_RETRIEVAL,
g_param_spec_boxed("ab-trans-retrieval",
"AQBanking Last Transaction Retrieval",
"The time of the last transaction retrieval for this "
"account.",
GNC_TYPE_TIMESPEC,
G_PARAM_READWRITE));
}
static void
@ -4279,6 +4432,80 @@ xaccAccountSetLastNum (Account *acc, const char *num)
xaccAccountCommitEdit (acc);
}
static Account *
GetOrMakeOrphanAccount (Account *root, gnc_commodity * currency)
{
char * accname;
Account * acc;
g_return_val_if_fail (root, NULL);
/* build the account name */
if (!currency)
{
PERR ("No currency specified!");
return NULL;
}
accname = g_strconcat (_("Orphaned Gains"), "-",
gnc_commodity_get_mnemonic (currency), NULL);
/* See if we've got one of these going already ... */
acc = gnc_account_lookup_by_name(root, accname);
if (acc == NULL)
{
/* Guess not. We'll have to build one. */
acc = xaccMallocAccount (gnc_account_get_book(root));
xaccAccountBeginEdit (acc);
xaccAccountSetName (acc, accname);
xaccAccountSetCommodity (acc, currency);
xaccAccountSetType (acc, ACCT_TYPE_INCOME);
xaccAccountSetDescription (acc, _("Realized Gain/Loss"));
xaccAccountSetNotes (acc,
_("Realized Gains or Losses from "
"Commodity or Trading Accounts "
"that haven't been recorded elsewhere."));
/* Hang the account off the root. */
gnc_account_append_child (root, acc);
xaccAccountCommitEdit (acc);
}
g_free (accname);
return acc;
}
Account *
xaccAccountGainsAccount (Account *acc, gnc_commodity *curr)
{
KvpFrame *frame = qof_instance_get_slots (QOF_INSTANCE (acc));
const gchar *curr_name = gnc_commodity_get_unique_name (curr);
GncGUID *guid;
Account *gains_account;
frame = kvp_frame_get_frame_slash (frame, "/lot-mgmt/gains-act/");
guid = kvp_frame_get_guid (frame, curr_name);
if (guid == NULL) /* No gains account for this currency */
{
gains_account = GetOrMakeOrphanAccount (gnc_account_get_root (acc),
curr);
guid = (GncGUID*)qof_instance_get_guid (QOF_INSTANCE (gains_account));
xaccAccountBeginEdit (acc);
{
kvp_frame_set_guid (frame, curr_name, guid);
qof_instance_set_dirty (QOF_INSTANCE (acc));
}
xaccAccountCommitEdit (acc);
}
else
gains_account = xaccAccountLookup (guid,
qof_instance_get_book(acc));
return gains_account;
}
/********************************************************************\
\********************************************************************/
@ -4718,6 +4945,508 @@ xaccAccountForEachTransaction(const Account *acc, TransactionCallback proc,
return xaccAccountStagedTransactionTraversal(acc, 42, proc, data);
}
/* ================================================================ */
/* The following functions are used by
* src/import-export/import-backend.c to manipulate the contra-account
* matching data. See src/import-export/import-backend.c for explanations.
*/
/* FIXME: These data are stored per-account in KVP and the functions
* work directly on KVP data structures. This prevents moving KVP to a
* backend-only abstraction.
*/
typedef struct _GncImportMatchMap
{
kvp_frame * frame;
Account * acc;
QofBook * book;
} GncImportMatchMap;
#define IMAP_FRAME "import-map"
#define IMAP_FRAME_BAYES "import-map-bayes"
GncImportMatchMap * gnc_account_create_imap (Account *acc);
Account* gnc_imap_find_account(GncImportMatchMap *imap, const char* category,
const char *key);
void gnc_imap_add_account (GncImportMatchMap *imap, const char *category,
const char *key, Account *acc);
Account* gnc_imap_find_account_bayes (GncImportMatchMap *imap, GList* tokens);
void gnc_imap_add_account_bayes (GncImportMatchMap *imap, GList* tokens,
Account *acc);
/* Obtain an ImportMatchMap object from an Account or a Book */
GncImportMatchMap *
gnc_account_create_imap (Account *acc)
{
GncImportMatchMap *imap;
kvp_frame *frame;
if (!acc) return NULL;
frame = qof_instance_get_slots (QOF_INSTANCE (acc));
g_return_val_if_fail (frame != NULL, NULL);
g_return_val_if_fail (frame != NULL, NULL);
imap = g_new0(GncImportMatchMap, 1);
imap->frame = frame;
/* Cache the book for easy lookups; store the account/book for
* marking dirtiness
*/
imap->acc = acc;
imap->book = gnc_account_get_book (acc);
return imap;
}
/* Look up an Account in the map */
Account*
gnc_imap_find_account (GncImportMatchMap *imap,
const char *category,
const char *key)
{
kvp_value *value;
GncGUID * guid;
if (!imap || !key) return NULL;
if (!category)
{
category = key;
key = NULL;
}
value = kvp_frame_get_slot_path (imap->frame, IMAP_FRAME,
category, key, NULL);
if (!value) return NULL;
guid = kvp_value_get_guid (value);
return xaccAccountLookup (guid, imap->book);
}
/* Store an Account in the map */
void
gnc_imap_add_account (GncImportMatchMap *imap,
const char *category,
const char *key,
Account *acc)
{
kvp_value *value;
if (!imap || !key || !acc || (strlen (key) == 0)) return;
if (!category)
{
category = key;
key = NULL;
}
g_return_if_fail (acc != NULL);
value = kvp_value_new_guid (xaccAccountGetGUID (acc));
g_return_if_fail (value != NULL);
xaccAccountBeginEdit (imap->acc);
kvp_frame_set_slot_path (imap->frame, value, IMAP_FRAME, category, key, NULL);
qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
xaccAccountCommitEdit (imap->acc);
kvp_value_delete (value);
/* XXX Mark the account (or book) as dirty! */
}
/*--------------------------------------------------------------------------
Below here is the bayes transaction to account matching system
--------------------------------------------------------------------------*/
struct account_token_count
{
char* account_name;
gint64 token_count; /**< occurances of a given token for this account_name */
};
/** total_count and the token_count for a given account let us calculate the
* probability of a given account with any single token
*/
struct token_accounts_info
{
GList *accounts; /**< array of struct account_token_count */
gint64 total_count;
};
/** gpointer is a pointer to a struct token_accounts_info
* \note Can always assume that keys are unique, reduces code in this function
*/
static void
buildTokenInfo(const char *key, kvp_value *value, gpointer data)
{
struct token_accounts_info *tokenInfo = (struct token_accounts_info*)data;
struct account_token_count* this_account;
// PINFO("buildTokenInfo: account '%s', token_count: '%ld'\n", (char*)key,
// (long)kvp_value_get_gint64(value));
/* add the count to the total_count */
tokenInfo->total_count += kvp_value_get_gint64(value);
/* allocate a new structure for this account and it's token count */
this_account = (struct account_token_count*)
g_new0(struct account_token_count, 1);
/* fill in the account name and number of tokens found for this account name */
this_account->account_name = (char*)key;
this_account->token_count = kvp_value_get_gint64(value);
/* append onto the glist a pointer to the new account_token_count structure */
tokenInfo->accounts = g_list_prepend(tokenInfo->accounts, this_account);
}
/** intermediate values used to calculate the bayes probability of a given account
where p(AB) = (a*b)/[a*b + (1-a)(1-b)], product is (a*b),
product_difference is (1-a) * (1-b)
*/
struct account_probability
{
double product; /* product of probabilities */
double product_difference; /* product of (1-probabilities) */
};
/** convert a hash table of account names and (struct account_probability*)
into a hash table of 100000x the percentage match value, ie. 10% would be
0.10 * 100000 = 10000
*/
#define PROBABILITY_FACTOR 100000
static void
buildProbabilities(gpointer key, gpointer value, gpointer data)
{
GHashTable *final_probabilities = (GHashTable*)data;
struct account_probability *account_p = (struct account_probability*)value;
/* P(AB) = A*B / [A*B + (1-A)*(1-B)]
* NOTE: so we only keep track of a running product(A*B*C...)
* and product difference ((1-A)(1-B)...)
*/
gint32 probability =
(account_p->product /
(account_p->product + account_p->product_difference))
* PROBABILITY_FACTOR;
PINFO("P('%s') = '%d'\n", (char*)key, probability);
g_hash_table_insert(final_probabilities, key, GINT_TO_POINTER(probability));
}
/** Frees an array of the same time that buildProperties built */
static void
freeProbabilities(gpointer key, gpointer value, gpointer data)
{
/* free up the struct account_probability that was allocated
* in gnc_account_find_account_bayes()
*/
g_free(value);
}
/** holds an account name and its corresponding integer probability
the integer probability is some factor of 10
*/
struct account_info
{
char* account_name;
gint32 probability;
};
/** Find the highest probability and the corresponding account name
store in data, a (struct account_info*)
NOTE: this is a g_hash_table_foreach() function for a hash table of entries
key is a pointer to the account name, value is a gint32, 100000x
the probability for this account
*/
static void
highestProbability(gpointer key, gpointer value, gpointer data)
{
struct account_info *account_i = (struct account_info*)data;
/* if the current probability is greater than the stored, store the current */
if (GPOINTER_TO_INT(value) > account_i->probability)
{
/* Save the new highest probability and the assoaciated account name */
account_i->probability = GPOINTER_TO_INT(value);
account_i->account_name = key;
}
}
#define threshold (.90 * PROBABILITY_FACTOR) /* 90% */
/** Look up an Account in the map */
Account*
gnc_imap_find_account_bayes (GncImportMatchMap *imap, GList *tokens)
{
struct token_accounts_info tokenInfo; /**< holds the accounts and total
* token count for a single token */
GList *current_token; /**< pointer to the current
* token from the input GList
* tokens */
GList *current_account_token; /**< pointer to the struct
* account_token_count */
struct account_token_count *account_c; /**< an account name and the number
* of times a token has appeared
* for the account */
struct account_probability *account_p; /**< intermediate storage of values
* to compute the bayes probability
* of an account */
GHashTable *running_probabilities = g_hash_table_new(g_str_hash,
g_str_equal);
GHashTable *final_probabilities = g_hash_table_new(g_str_hash,
g_str_equal);
struct account_info account_i;
kvp_value* value;
kvp_frame* token_frame;
ENTER(" ");
/* check to see if the imap is NULL */
if (!imap)
{
PINFO("imap is null, returning null");
LEAVE(" ");
return NULL;
}
/* find the probability for each account that contains any of the tokens
* in the input tokens list
*/
for (current_token = tokens; current_token;
current_token = current_token->next)
{
/* zero out the token_accounts_info structure */
memset(&tokenInfo, 0, sizeof(struct token_accounts_info));
PINFO("token: '%s'", (char*)current_token->data);
/* find the slot for the given token off of the source account
* for these tokens, search off of the IMAP_FRAME_BAYES path so
* we aren't looking from the parent of the entire kvp tree
*/
value = kvp_frame_get_slot_path(imap->frame, IMAP_FRAME_BAYES,
(char*)current_token->data, NULL);
/* if value is null we should skip over this token */
if (!value)
continue;
/* convert the slot(value) into a the frame that contains the
* list of accounts
*/
token_frame = kvp_value_get_frame(value);
/* token_frame should NEVER be null */
if (!token_frame)
{
PERR("token '%s' has no accounts", (char*)current_token->data);
continue; /* skip over this token */
}
/* process the accounts for this token, adding the account if it
* doesn't already exist or adding to the existing accounts token
* count if it does
*/
kvp_frame_for_each_slot(token_frame, buildTokenInfo, &tokenInfo);
/* for each account we have just found, see if the account
* already exists in the list of account probabilities, if not
* add it
*/
for (current_account_token = tokenInfo.accounts; current_account_token;
current_account_token = current_account_token->next)
{
/* get the account name and corresponding token count */
account_c = (struct account_token_count*)current_account_token->data;
PINFO("account_c->account_name('%s'), "
"account_c->token_count('%ld')/total_count('%ld')",
account_c->account_name, (long)account_c->token_count,
(long)tokenInfo.total_count);
account_p = g_hash_table_lookup(running_probabilities,
account_c->account_name);
/* if the account exists in the list then continue
* the running probablities
*/
if (account_p)
{
account_p->product = (((double)account_c->token_count /
(double)tokenInfo.total_count)
* account_p->product);
account_p->product_difference =
((double)1 - ((double)account_c->token_count /
(double)tokenInfo.total_count))
* account_p->product_difference;
PINFO("product == %f, product_difference == %f",
account_p->product, account_p->product_difference);
}
else
{
/* add a new entry */
PINFO("adding a new entry for this account");
account_p = (struct account_probability*)
g_new0(struct account_probability, 1);
/* set the product and product difference values */
account_p->product = ((double)account_c->token_count /
(double)tokenInfo.total_count);
account_p->product_difference =
(double)1 - ((double)account_c->token_count /
(double)tokenInfo.total_count);
PINFO("product == %f, product_difference == %f",
account_p->product, account_p->product_difference);
/* add the account name and (struct account_probability*)
* to the hash table */
g_hash_table_insert(running_probabilities,
account_c->account_name, account_p);
}
} /* for all accounts in tokenInfo */
/* free the data in tokenInfo */
for (current_account_token = tokenInfo.accounts; current_account_token;
current_account_token = current_account_token->next)
{
/* free up each struct account_token_count we allocated */
g_free((struct account_token_count*)current_account_token->data);
}
g_list_free(tokenInfo.accounts); /* free the accounts GList */
}
/* build a hash table of account names and their final probabilities
* from each entry in the running_probabilties hash table
*/
g_hash_table_foreach(running_probabilities, buildProbabilities,
final_probabilities);
/* find the highest probabilty and the corresponding account */
memset(&account_i, 0, sizeof(struct account_info));
g_hash_table_foreach(final_probabilities, highestProbability, &account_i);
/* free each element of the running_probabilities hash */
g_hash_table_foreach(running_probabilities, freeProbabilities, NULL);
/* free the hash tables */
g_hash_table_destroy(running_probabilities);
g_hash_table_destroy(final_probabilities);
PINFO("highest P('%s') = '%d'",
account_i.account_name ? account_i.account_name : "(null)",
account_i.probability);
/* has this probability met our threshold? */
if (account_i.probability >= threshold)
{
PINFO("found match");
LEAVE(" ");
return gnc_account_lookup_by_full_name(gnc_book_get_root_account(imap->book),
account_i.account_name);
}
PINFO("no match");
LEAVE(" ");
return NULL; /* we didn't meet our threshold, return NULL for an account */
}
/** Updates the imap for a given account using a list of tokens */
void
gnc_imap_add_account_bayes(GncImportMatchMap *imap,
GList *tokens,
Account *acc)
{
GList *current_token;
kvp_value *value;
gint64 token_count;
char* account_fullname;
kvp_value *new_value; /* the value that will be added back into
* the kvp tree */
ENTER(" ");
/* if imap is null return */
if (!imap)
{
LEAVE(" ");
return;
}
g_return_if_fail (acc != NULL);
account_fullname = gnc_account_get_full_name(acc);
xaccAccountBeginEdit (imap->acc);
PINFO("account name: '%s'\n", account_fullname);
/* process each token in the list */
for (current_token = g_list_first(tokens); current_token;
current_token = current_token->next)
{
/* Jump to next iteration if the pointer is not valid or if the
string is empty. In HBCI import we almost always get an empty
string, which doesn't work in the kvp loopkup later. So we
skip this case here. */
if (!current_token->data || (*((char*)current_token->data) == '\0'))
continue;
/* start off with no tokens for this account */
token_count = 0;
PINFO("adding token '%s'\n", (char*)current_token->data);
/* is this token/account_name already in the kvp tree? */
value = kvp_frame_get_slot_path(imap->frame, IMAP_FRAME_BAYES,
(char*)current_token->data,
account_fullname,
NULL);
/* if the token/account is already in the tree, read the current
* value from the tree and use this for the basis of the value we
* are putting back
*/
if (value)
{
PINFO("found existing value of '%ld'\n",
(long)kvp_value_get_gint64(value));
/* convert this value back into an integer */
token_count += kvp_value_get_gint64(value);
}
/* increment the token count */
token_count++;
/* create a new value */
new_value = kvp_value_new_gint64(token_count);
/* insert the value into the kvp tree at
* /imap->frame/IMAP_FRAME/token_string/account_name_string
*/
kvp_frame_set_slot_path(imap->frame, new_value,
IMAP_FRAME_BAYES,
(char*)current_token->data,
account_fullname,
NULL);
/* kvp_frame_set_slot_path() copied the value so we
* need to delete this one ;-) */
kvp_value_delete(new_value);
}
/* free up the account fullname string */
qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
xaccAccountCommitEdit (imap->acc);
g_free(account_fullname);
LEAVE(" ");
}
/* ================================================================ */
/* QofObject function implementation and registration */

View File

@ -417,6 +417,17 @@ void xaccAccountSortSplits (Account *acc, gboolean force);
*/
gchar * gnc_account_get_full_name (const Account *account);
/** Retrieve the gains account used by this account for the indicated
* currency, creating and recording a new one if necessary.
*
* FIXME: There is at present no interface to designate an existing
* account, and the new account name is hard coded to
* "Orphaned Gains -- CUR"
*
* FIXME: There is no provision for creating separate accounts for
* anything other than currency, e.g. holding period of a security.
*/
Account * xaccAccountGainsAccount (Account *acc, gnc_commodity *curr);
/** Set a string that identifies the Finance::Quote backend that
* should be used to retrieve online prices. See price-quotes.scm
* for more information
@ -860,8 +871,6 @@ gboolean xaccAccountGetReconcileChildrenStatus(const Account *account);
*/
gboolean xaccAccountHasAncestor(const Account *acc, const Account *ancestor);
#define xaccAccountGetSlots(X) qof_instance_get_slots(QOF_INSTANCE(X))
/** @} */
/** @name Lookup Accounts and Subaccounts by name or code

View File

@ -150,6 +150,9 @@ sxtg_is_dirty(const QofCollection *col)
return dirty;
}
/* EFFECTIVE FRIEND FUNCTION declared in qofinstance-p.h */
extern void qof_instance_mark_clean (QofInstance *);
static void
sxtg_mark_clean(QofCollection *col)
{
@ -372,9 +375,9 @@ gnc_sx_get_sxes_referencing_account(QofBook *book, Account *acct)
for (; splits != NULL; splits = splits->next)
{
Split *s = (Split*)splits->data;
KvpFrame *frame = kvp_frame_get_frame(xaccSplitGetSlots(s), GNC_SX_ID);
GncGUID *sx_split_acct_guid = kvp_frame_get_guid(frame, GNC_SX_ACCOUNT);
if (guid_equal(acct_guid, sx_split_acct_guid))
GncGUID *guid = NULL;
qof_instance_get (QOF_INSTANCE (s), "sx-account", &guid, NULL);
if (guid_equal(acct_guid, guid))
{
rtn = g_list_append(rtn, sx);
}

View File

@ -36,6 +36,7 @@
#include "Transaction.h"
#include "gnc-engine.h"
#include "engine-helpers.h"
#include "qofinstance-p.h"
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "gnc.engine.sx"
@ -43,19 +44,19 @@
enum
{
PROP_0,
PROP_NAME,
PROP_ENABLED,
PROP_NUM_OCCURANCE,
PROP_REM_OCCURANCE,
PROP_AUTO_CREATE,
PROP_AUTO_CREATE_NOTIFY,
PROP_ADVANCE_CREATION_DAYS,
PROP_ADVANCE_REMINDER_DAYS,
PROP_START_DATE,
PROP_END_DATE,
PROP_LAST_OCCURANCE_DATE,
PROP_INSTANCE_COUNT,
PROP_TEMPLATE_ACCOUNT
PROP_NAME, /* Table */
PROP_ENABLED, /* Table */
PROP_START_DATE, /* Table */
PROP_END_DATE, /* Table */
PROP_LAST_OCCURANCE_DATE, /* Table */
PROP_NUM_OCCURANCE, /* Table */
PROP_REM_OCCURANCE, /* Table */
PROP_AUTO_CREATE, /* Table */
PROP_AUTO_CREATE_NOTIFY, /* Table */
PROP_ADVANCE_CREATION_DAYS, /* Table */
PROP_ADVANCE_REMINDER_DAYS, /* Table */
PROP_INSTANCE_COUNT, /* Table */
PROP_TEMPLATE_ACCOUNT /* Table */
};
/* GObject initialization */
@ -173,6 +174,8 @@ gnc_schedxaction_set_property (GObject *object,
g_return_if_fail(GNC_IS_SCHEDXACTION(object));
sx = GNC_SCHEDXACTION(object);
g_assert (qof_instance_get_editlevel(sx));
switch (prop_id)
{
case PROP_NAME:
@ -1042,8 +1045,8 @@ pack_split_info (TTSplitInfo *s_info, Account *parent_acct,
Transaction *parent_trans, QofBook *book)
{
Split *split;
KvpFrame *split_frame;
KvpValue *tmp_value;
const gchar *credit_formula;
const gchar *debit_formula;
const GncGUID *acc_guid;
split = xaccMallocSplit(book);
@ -1059,40 +1062,14 @@ pack_split_info (TTSplitInfo *s_info, Account *parent_acct,
xaccAccountInsertSplit(parent_acct,
split);
split_frame = xaccSplitGetSlots(split);
tmp_value
= kvp_value_new_string(gnc_ttsplitinfo_get_credit_formula(s_info));
kvp_frame_set_slot_path(split_frame,
tmp_value,
GNC_SX_ID,
GNC_SX_CREDIT_FORMULA,
NULL);
kvp_value_delete(tmp_value);
tmp_value
= kvp_value_new_string(gnc_ttsplitinfo_get_debit_formula(s_info));
kvp_frame_set_slot_path(split_frame,
tmp_value,
GNC_SX_ID,
GNC_SX_DEBIT_FORMULA,
NULL);
kvp_value_delete(tmp_value);
credit_formula = gnc_ttsplitinfo_get_credit_formula(s_info);
debit_formula = gnc_ttsplitinfo_get_debit_formula(s_info);
acc_guid = qof_entity_get_guid(QOF_INSTANCE(gnc_ttsplitinfo_get_account(s_info)));
tmp_value = kvp_value_new_guid(acc_guid);
kvp_frame_set_slot_path(split_frame,
tmp_value,
GNC_SX_ID,
GNC_SX_ACCOUNT,
NULL);
kvp_value_delete(tmp_value);
qof_instance_set (QOF_INSTANCE (split),
"sx-credit-formula", credit_formula,
"sx-debit-formula", debit_formula,
"sx-account", acc_guid,
NULL);
return split;
}

View File

@ -304,15 +304,7 @@ void gnc_sx_remove_defer_instance( SchedXaction *sx, void *deferStateData );
GList *gnc_sx_get_defer_instances( SchedXaction *sx );
/* #defines for KvpFrame strings and QOF */
#define GNC_SX_ID "sched-xaction"
#define GNC_SX_ACCOUNT "account"
#define GNC_SX_CREDIT_FORMULA "credit-formula"
#define GNC_SX_DEBIT_FORMULA "debit-formula"
#define GNC_SX_CREDIT_NUMERIC "credit-numeric"
#define GNC_SX_DEBIT_NUMERIC "debit-numeric"
#define GNC_SX_SHARES "shares"
#define GNC_SX_AMOUNT "amnt"
#define GNC_SX_FROM_SCHED_XACTION "from-sched-xaction"
#define GNC_SX_FREQ_SPEC "scheduled-frequency"
#define GNC_SX_NAME "sched-xname"
#define GNC_SX_START_DATE "sched-start-date"

View File

@ -1133,6 +1133,9 @@ xaccAccountScrubCommodity (Account *account)
/* ================================================================ */
/* EFFECTIVE FRIEND FUNCTION declared in qofinstance-p.h */
extern void qof_instance_set_dirty (QofInstance*);
static void
xaccAccountDeleteOldData (Account *account)
{

View File

@ -157,7 +157,7 @@ xaccLotScrubDoubleBalance (GNCLot *lot)
if (!lot) return;
ENTER ("lot=%s", kvp_frame_get_string (gnc_lot_get_slots (lot), "/title"));
ENTER ("lot=%s", gnc_lot_get_title(lot));
for (snode = gnc_lot_get_split_list(lot); snode; snode = snode->next)
{
@ -216,7 +216,7 @@ xaccLotScrubDoubleBalance (GNCLot *lot)
}
}
LEAVE ("lot=%s", kvp_frame_get_string (gnc_lot_get_slots (lot), "/title"));
LEAVE ("lot=%s", gnc_lot_get_title(lot));
}
/* ================================================================= */

View File

@ -51,6 +51,7 @@
#include "gnc-engine.h"
#include "gnc-lot.h"
#include "gnc-event.h"
#include "qofinstance-p.h"
const char *void_former_amt_str = "void-former-amount";
const char *void_former_val_str = "void-former-value";
@ -60,17 +61,40 @@ const char *void_former_val_str = "void-former-value";
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_ENGINE;
/* KVP key values used for SX info stored Split's slots. */
#define GNC_SX_ID "sched-xaction"
#define GNC_SX_ACCOUNT "account"
#define GNC_SX_CREDIT_FORMULA "credit-formula"
#define GNC_SX_DEBIT_FORMULA "debit-formula"
#define GNC_SX_CREDIT_NUMERIC "credit-numeric"
#define GNC_SX_DEBIT_NUMERIC "debit-numeric"
#define GNC_SX_SHARES "shares"
enum
{
PROP_0,
PROP_ACTION,
PROP_MEMO,
PROP_VALUE,
PROP_AMOUNT,
PROP_RECONCILE_DATE,
PROP_TX,
PROP_ACCOUNT,
PROP_LOT
PROP_TX, /* Table */
PROP_ACCOUNT, /* Table */
PROP_MEMO, /* Table */
PROP_ACTION, /* Table */
// PROP_RECONCILE_STATE, /* Table */
PROP_RECONCILE_DATE, /* Table */
PROP_VALUE, /* Table, in 2 fields */
PROP_SX_ACCOUNT, /* KVP */
PROP_SX_CREDIT_FORMULA, /* KVP */
PROP_SX_CREDIT_NUMERIC, /* KVP */
PROP_SX_DEBIT_FORMULA, /* KVP */
PROP_SX_DEBIT_NUMERIC, /* KVP */
PROP_SX_SHARES, /* KVP */
PROP_LOT, /* KVP */
PROP_ONLINE_ACCOUNT, /* KVP */
PROP_LOT_SPLIT, /* KVP */
PROP_PEER_GUID, /* KVP */
PROP_GAINS_SPLIT, /* KVP */
PROP_GAINS_SOURCE, /* KVP */
PROP_RUNTIME_0,
PROP_AMOUNT, /* Runtime */
};
/* GObject Initialization */
@ -126,6 +150,7 @@ gnc_split_get_property(GObject *object,
GParamSpec *pspec)
{
Split *split;
gchar *key;
g_return_if_fail(GNC_IS_SPLIT(object));
@ -156,6 +181,50 @@ gnc_split_get_property(GObject *object,
case PROP_LOT:
g_value_take_object(value, split->lot);
break;
case PROP_SX_CREDIT_FORMULA:
key = GNC_SX_ID "/" GNC_SX_CREDIT_FORMULA;
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_SX_CREDIT_NUMERIC:
key = GNC_SX_ID "/" GNC_SX_CREDIT_NUMERIC;
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_SX_DEBIT_FORMULA:
key = GNC_SX_ID "/" GNC_SX_DEBIT_FORMULA;
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_SX_DEBIT_NUMERIC:
key = GNC_SX_ID "/" GNC_SX_DEBIT_NUMERIC;
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_SX_ACCOUNT:
key = GNC_SX_ID "/" GNC_SX_ACCOUNT;
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_SX_SHARES:
key = GNC_SX_ID "/" GNC_SX_SHARES;
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_ONLINE_ACCOUNT:
key = "online_id";
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_LOT_SPLIT:
key = "lot-split";
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_PEER_GUID:
key = "peer_guid";
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_GAINS_SPLIT:
key = "gains-split";
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_GAINS_SOURCE:
key = "gains-source";
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -170,10 +239,14 @@ gnc_split_set_property(GObject *object,
{
Split *split;
gnc_numeric* number;
gchar *key;
g_return_if_fail(GNC_IS_SPLIT(object));
split = GNC_SPLIT(object);
if (prop_id < PROP_RUNTIME_0 && split->parent != NULL)
g_assert (qof_instance_get_editlevel(split->parent));
switch (prop_id)
{
case PROP_ACTION:
@ -202,6 +275,50 @@ gnc_split_set_property(GObject *object,
case PROP_LOT:
xaccSplitSetLot(split, g_value_get_object(value));
break;
case PROP_SX_CREDIT_FORMULA:
key = GNC_SX_ID "/" GNC_SX_CREDIT_FORMULA;
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_SX_CREDIT_NUMERIC:
key = GNC_SX_ID "/" GNC_SX_CREDIT_NUMERIC;
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_SX_DEBIT_FORMULA:
key = GNC_SX_ID "/" GNC_SX_DEBIT_FORMULA;
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_SX_DEBIT_NUMERIC:
key = GNC_SX_ID "/" GNC_SX_DEBIT_NUMERIC;
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_SX_ACCOUNT:
key = GNC_SX_ID "/" GNC_SX_ACCOUNT;
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_SX_SHARES:
key = GNC_SX_ID "/" GNC_SX_SHARES;
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_ONLINE_ACCOUNT:
key = "online_id";
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_LOT_SPLIT:
key = "lot-split";
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_PEER_GUID:
key = "peer_guid";
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_GAINS_SPLIT:
key = "gains-split";
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
break;
case PROP_GAINS_SOURCE:
key = "gains-source";
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -299,6 +416,122 @@ gnc_split_class_init(SplitClass* klass)
"The lot that this split belongs to.",
GNC_TYPE_LOT,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_SX_DEBIT_FORMULA,
g_param_spec_string("sx-debit-formula",
"Schedule Transaction Debit Formula",
"The formula used to calculate the actual debit "
"amount when a real split is generated from this "
"SX split.",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_SX_DEBIT_NUMERIC,
g_param_spec_boxed("sx-debit-numeric",
"Scheduled Transaction Debit Numeric",
"Numeric value to plug into the Debit Formula when a "
"real split is generated from this SX split.",
GNC_TYPE_NUMERIC,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_SX_CREDIT_FORMULA,
g_param_spec_string("sx-credit-formula",
"Schedule Transaction Credit Formula",
"The formula used to calculate the actual credit "
"amount when a real split is generated from this "
"SX split.",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_SX_CREDIT_NUMERIC,
g_param_spec_boxed("sx-credit-numeric",
"Scheduled Transaction Credit Numeric",
"Numeric value to plug into the Credit Formula when a "
"real split is generated from this SX split.",
GNC_TYPE_NUMERIC,
G_PARAM_READWRITE));
/* FIXME: PROP_SX_SHARES should be stored as a gnc_numeric, but the function
* which uses it, gnc_template_register_save_shares_cell, stores a
* phony string. This is maintained until backwards compatibility can
* be established.
*/
g_object_class_install_property
(gobject_class,
PROP_SX_SHARES,
g_param_spec_string("sx-shares",
"Scheduled Transaction Shares",
"Numeric value of shares to insert in a new split when "
"it's generated from this SX split.",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_SX_ACCOUNT,
g_param_spec_boxed("sx-account",
"Scheduled Transaction Account",
"The target account for a scheduled transaction split.",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_ONLINE_ACCOUNT,
g_param_spec_string ("online-id",
"Online Account ID",
"The online account which corresponds to this "
"account for OFX/HCBI import",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_LOT_SPLIT,
g_param_spec_int64 ("lot-split",
"Lot Split",
"Indicates that the split was divided into two "
"splits in order to balance a lot capital gains "
"transaction. Contains a timestamp of the action.",
G_MININT64, G_MAXINT64, 0,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_PEER_GUID,
g_param_spec_boxed ("peer-guid",
"Peer GUID",
"The other split in the division.",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_GAINS_SPLIT,
g_param_spec_boxed ("gains-split",
"Gains Split",
"The capital gains split associated with this "
"split when this split represents the proceeds "
"from the sale of a commodity inside a Lot.",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_GAINS_SOURCE,
g_param_spec_boxed ("gains-source",
"Gains Source",
"The source split for which this split this is "
"the gains split. ",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
}
/********************************************************************\
@ -406,7 +639,7 @@ xaccDupeSplit (const Split *s)
}
Split *
xaccSplitClone (const Split *s)
xaccSplitCloneNoKvp (const Split *s)
{
Split *split = g_object_new (GNC_TYPE_SPLIT, NULL);
@ -424,10 +657,8 @@ xaccSplitClone (const Split *s)
split->gains = GAINS_STATUS_UNKNOWN;
split->gains_split = NULL;
qof_instance_init_data(&split->inst, GNC_ID_SPLIT, qof_instance_get_book(s));
kvp_frame_delete(split->inst.kvp_data);
split->inst.kvp_data = kvp_frame_copy(s->inst.kvp_data);
qof_instance_init_data(&split->inst, GNC_ID_SPLIT,
qof_instance_get_book(s));
xaccAccountInsertSplit(s->acc, split);
if (s->lot)
{
@ -437,6 +668,11 @@ xaccSplitClone (const Split *s)
return split;
}
void
xaccSplitCopyKvp (const Split *from, Split *to)
{
to->inst.kvp_data = kvp_frame_copy(from->inst.kvp_data);
}
/*################## Added for Reg2 #################*/
@ -954,26 +1190,6 @@ get_commodity_denom(const Split * s)
}
}
/********************************************************************
* xaccSplitGetSlots
********************************************************************/
KvpFrame *
xaccSplitGetSlots (const Split * s)
{
return qof_instance_get_slots(QOF_INSTANCE(s));
}
/* Used for testing only: _get_random_split in test-engine-stuff.c */
void
xaccSplitSetSlots_nc(Split *s, KvpFrame *frm)
{
if (!s || !frm) return;
xaccTransBeginEdit(s->parent);
qof_instance_set_slots(QOF_INSTANCE(s), frm);
xaccTransCommitEdit(s->parent);
}
/********************************************************************\
\********************************************************************/
@ -2115,7 +2331,7 @@ gboolean xaccSplitRegister (void)
{ SPLIT_ACCT_FULLNAME, SPLIT_ACCT_FULLNAME, no_op, NULL },
{ SPLIT_CORR_ACCT_NAME, SPLIT_CORR_ACCT_NAME, no_op, NULL },
{ SPLIT_CORR_ACCT_CODE, SPLIT_CORR_ACCT_CODE, no_op, NULL },
{ SPLIT_KVP, QOF_TYPE_KVP, (QofAccessFunc)xaccSplitGetSlots, NULL },
{ SPLIT_KVP, QOF_TYPE_KVP, (QofAccessFunc)qof_instance_get_slots, NULL },
{ QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)xaccSplitGetBook, NULL },
{
QOF_PARAM_GUID, QOF_TYPE_GUID,

View File

@ -144,20 +144,6 @@ GNCLot * xaccSplitGetLot (const Split *split);
/** Assigns the split to a specific Lot */
void xaccSplitSetLot(Split* split, GNCLot* lot);
/** Returns the KvpFrame slots of this split for direct editing.
*
* Split slots are used to store arbitrary strings, numbers, and
* structures which aren't members of the transaction struct. See
* kvp_doc.txt for reserved slot names.
*/
KvpFrame *xaccSplitGetSlots(const Split *split);
/** Set the KvpFrame slots of this split to the given frm by directly
* using the frm pointer (i.e. non-copying). */
void xaccSplitSetSlots_nc(Split *s, KvpFrame *frm);
/** The memo is an arbitrary string associated with a split. It is
* intended to hold a short (zero to forty character) string that is
* displayed by the GUI along with this split. Users typically type

View File

@ -146,7 +146,8 @@ struct _SplitClass
*/
void xaccFreeSplit (Split *split); /* frees memory */
Split * xaccSplitClone (const Split *s);
Split *xaccSplitCloneNoKvp (const Split *s);
void xaccSplitCopyKvp (const Split *from, Split *to);
Split *xaccDupeSplit (const Split *s);
void mark_split (Split *s);

View File

@ -184,6 +184,7 @@ const char *assoc_uri_str = "assoc_uri";
#define TRANS_TXN_TYPE_KVP "trans-txn-type"
#define TRANS_READ_ONLY_REASON "trans-read-only"
#define TRANS_REVERSED_BY "reversed-by"
#define GNC_SX_FROM "from-sched-xaction"
#define ISO_DATELENGTH 32 /* length of an iso 8601 date string. */
@ -193,11 +194,14 @@ static QofLogModule log_module = GNC_MOD_ENGINE;
enum
{
PROP_0,
PROP_NUM,
PROP_DESCRIPTION,
PROP_CURRENCY,
PROP_POST_DATE,
PROP_ENTER_DATE
PROP_CURRENCY, /* Table */
PROP_NUM, /* Table */
PROP_POST_DATE, /* Table */
PROP_ENTER_DATE, /* Table */
PROP_DESCRIPTION, /* Table */
PROP_INVOICE, /* KVP */
PROP_SX_TXN, /* KVP */
PROP_ONLINE_ACCOUNT,/* KVP */
};
void
@ -303,6 +307,9 @@ gnc_transaction_get_property(GObject* object,
GParamSpec* pspec)
{
Transaction* tx;
KvpFrame *frame;
gchar *key;
GValue *temp;
g_return_if_fail(GNC_IS_TRANSACTION(object));
@ -324,6 +331,18 @@ gnc_transaction_get_property(GObject* object,
case PROP_ENTER_DATE:
g_value_set_boxed(value, &tx->date_entered);
break;
case PROP_INVOICE:
key = GNC_INVOICE_ID "/" GNC_INVOICE_GUID;
qof_instance_get_kvp (QOF_INSTANCE (tx), key, value);
break;
case PROP_SX_TXN:
key = GNC_SX_FROM;
qof_instance_get_kvp (QOF_INSTANCE (tx), key, value);
break;
case PROP_ONLINE_ACCOUNT:
key = "online_id";
qof_instance_get_kvp (QOF_INSTANCE (tx), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -337,10 +356,14 @@ gnc_transaction_set_property(GObject* object,
GParamSpec* pspec)
{
Transaction* tx;
KvpFrame *frame;
gchar *key;
g_return_if_fail(GNC_IS_TRANSACTION(object));
tx = GNC_TRANSACTION(object);
g_assert (qof_instance_get_editlevel(tx));
switch (prop_id)
{
case PROP_NUM:
@ -358,6 +381,18 @@ gnc_transaction_set_property(GObject* object,
case PROP_ENTER_DATE:
xaccTransSetDateEnteredTS(tx, g_value_get_boxed(value));
break;
case PROP_INVOICE:
key = GNC_INVOICE_ID "/" GNC_INVOICE_GUID;
qof_instance_set_kvp (QOF_INSTANCE (tx), key, value);
break;
case PROP_SX_TXN:
key = GNC_SX_FROM;
qof_instance_set_kvp (QOF_INSTANCE (tx), key, value);
break;
case PROP_ONLINE_ACCOUNT:
key = "online_id";
qof_instance_set_kvp (QOF_INSTANCE (tx), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -426,6 +461,36 @@ gnc_transaction_class_init(TransactionClass* klass)
"The date the transaction was entered.",
GNC_TYPE_TIMESPEC,
G_PARAM_READWRITE));
g_object_class_install_property(
gobject_class,
PROP_INVOICE,
g_param_spec_boxed("invoice",
"Invoice attached to lot",
"Used by GncInvoice",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
g_object_class_install_property(
gobject_class,
PROP_SX_TXN,
g_param_spec_boxed("from-sched-xaction",
"From Scheduled Transaction",
"Used by Scheduled Transastions to record the "
"originating template transaction for created "
"transactions",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_ONLINE_ACCOUNT,
g_param_spec_string ("online-id",
"Online Account ID",
"The online account which corresponds to this "
"account for OFX/HCBI import",
NULL,
G_PARAM_READWRITE));
}
/********************************************************************\
@ -532,9 +597,8 @@ xaccTransSortSplits (Transaction *trans)
* This routine is prone to programmer snafu if not used correctly.
* It is used only by the edit-rollback code.
*/
/* Actually, it *is* public, and used by Period.c */
Transaction *
xaccDupeTransaction (const Transaction *from)
static Transaction *
dupe_trans (const Transaction *from)
{
Transaction *to;
GList *node;
@ -571,10 +635,11 @@ xaccDupeTransaction (const Transaction *from)
/********************************************************************\
* Use this routine to externally duplicate a transaction. It creates
* a full fledged transaction with unique guid, splits, etc.
* a full fledged transaction with unique guid, splits, etc. and
* writes it to the database.
\********************************************************************/
Transaction *
xaccTransClone (const Transaction *from)
xaccTransCloneNoKvp (const Transaction *from)
{
Transaction *to;
Split *split;
@ -593,14 +658,13 @@ xaccTransClone (const Transaction *from)
to->orig = NULL;
qof_instance_init_data (&to->inst, GNC_ID_TRANS, qof_instance_get_book(from));
kvp_frame_delete (to->inst.kvp_data);
to->inst.kvp_data = kvp_frame_copy (from->inst.kvp_data);
qof_instance_init_data (&to->inst, GNC_ID_TRANS,
qof_instance_get_book(from));
xaccTransBeginEdit(to);
for (node = from->splits; node; node = node->next)
{
split = xaccSplitClone(node->data);
split = xaccSplitCloneNoKvp(node->data);
split->parent = to;
to->splits = g_list_append (to->splits, split);
}
@ -611,11 +675,28 @@ xaccTransClone (const Transaction *from)
return to;
}
Transaction *
xaccTransClone (const Transaction *from)
{
Transaction *to = xaccTransCloneNoKvp (from);
int i = 0;
int length = g_list_length (from->splits);
xaccTransBeginEdit (to);
to->inst.kvp_data = kvp_frame_copy (from->inst.kvp_data);
g_assert (g_list_length (to->splits) == length);
for (i = 0; i < length; ++i)
xaccSplitCopyKvp (g_list_nth_data (from->splits, i),
g_list_nth_data (to->splits, i));
xaccTransCommitEdit (to);
return to;
}
/*################## Added for Reg2 #################*/
/********************************************************************\
* Copy a transaction to the 'clipboard' transaction using
* xaccDupeTransaction. The 'clipboard' transaction must never
* dupe_trans. The 'clipboard' transaction must never
* be dereferenced.
\********************************************************************/
Transaction * xaccTransCopyToClipBoard(const Transaction *from_trans)
@ -625,7 +706,7 @@ Transaction * xaccTransCopyToClipBoard(const Transaction *from_trans)
if (!from_trans)
return NULL;
to_trans = xaccDupeTransaction(from_trans);
to_trans = dupe_trans(from_trans);
return to_trans;
}
@ -642,7 +723,7 @@ xaccTransCopyOnto(const Transaction *from_trans, Transaction *to_trans)
/********************************************************************\
* This function explicitly must robustly handle some unusual input.
*
* 'from_trans' may be a duped trans (see xaccDupeTransaction), so its
* 'from_trans' may be a duped trans (see dupe_trans), so its
* splits may not really belong to the accounts that they say they do.
*
* 'from_acc' need not be a valid account. It may be an already freed
@ -1309,7 +1390,7 @@ xaccTransBeginEdit (Transaction *trans)
/* Make a clone of the transaction; we will use this
* in case we need to roll-back the edit. */
trans->orig = xaccDupeTransaction (trans);
trans->orig = dupe_trans (trans);
}
/********************************************************************\
@ -2615,6 +2696,7 @@ xaccTransFindSplitByAccount(const Transaction *trans, const Account *acc)
return NULL;
}
/********************************************************************\
\********************************************************************/
/* QofObject function implementation */
@ -2776,6 +2858,7 @@ _utest_trans_fill_functions (void)
func->trans_on_error = trans_on_error;
func->trans_cleanup_commit = trans_cleanup_commit;
func->xaccTransScrubGainsDate = xaccTransScrubGainsDate;
func->dupe_trans = dupe_trans;
return func;
}

View File

@ -156,6 +156,12 @@ void xaccTransDestroy (Transaction *trans);
*/
Transaction * xaccTransClone (const Transaction *t);
/**
The xaccTransCloneNoKvp() method will create a complete copy of an
existing transaction except that the KVP slots will be empty.
*/
Transaction * xaccTransCloneNoKvp (const Transaction *t);
/** Equality.
*
* @param ta First transaction to compare
@ -223,7 +229,7 @@ Transaction * xaccTransLookup (const GncGUID *guid, QofBook *book);
/*################## Added for Reg2 #################*/
/** Copy a transaction to the 'clipboard' transaction using
* xaccDupeTransaction. The 'clipboard' transaction must never
* dupe_transaction. The 'clipboard' transaction must never
* be dereferenced.
*/
Transaction * xaccTransCopyToClipBoard(const Transaction *from_trans);
@ -749,8 +755,6 @@ void xaccTransDump (const Transaction *trans, const char *tag);
#define xaccTransGetGUID(X) qof_entity_get_guid(QOF_INSTANCE(X))
/** \deprecated */
#define xaccTransReturnGUID(X) (X ? *(qof_entity_get_guid(QOF_INSTANCE(X))) : *(guid_null()))
/** \deprecated */
#define xaccTransGetSlots(X) qof_instance_get_slots (QOF_INSTANCE(X))
#endif /* XACC_TRANSACTION_H */
/** @} */

View File

@ -186,6 +186,7 @@ typedef struct
void (*trans_on_error)(Transaction*, QofBackendError);
void (*trans_cleanup_commit)(Transaction*);
void (*xaccTransScrubGainsDate)(Transaction*);
Transaction *(*dupe_trans)(const Transaction*);
} TransTestFunctions;

View File

@ -215,150 +215,6 @@ xaccAccountFindLatestOpenLot (Account *acc, gnc_numeric sign,
return lot;
}
/* ============================================================== */
/* Similar to GetOrMakeAccount, but different in important ways */
static Account *
GetOrMakeLotOrphanAccount (Account *root, gnc_commodity * currency)
{
char * accname;
Account * acc;
g_return_val_if_fail (root, NULL);
/* build the account name */
if (!currency)
{
PERR ("No currency specified!");
return NULL;
}
accname = g_strconcat (_("Orphaned Gains"), "-",
gnc_commodity_get_mnemonic (currency), NULL);
/* See if we've got one of these going already ... */
acc = gnc_account_lookup_by_name(root, accname);
if (acc == NULL)
{
/* Guess not. We'll have to build one. */
acc = xaccMallocAccount (gnc_account_get_book(root));
xaccAccountBeginEdit (acc);
xaccAccountSetName (acc, accname);
xaccAccountSetCommodity (acc, currency);
xaccAccountSetType (acc, ACCT_TYPE_INCOME);
xaccAccountSetDescription (acc, _("Realized Gain/Loss"));
xaccAccountSetNotes (acc,
_("Realized Gains or Losses from "
"Commodity or Trading Accounts "
"that haven't been recorded elsewhere."));
/* Hang the account off the root. */
gnc_account_append_child (root, acc);
xaccAccountCommitEdit (acc);
}
g_free (accname);
return acc;
}
/* ============================================================== */
void
xaccAccountSetDefaultGainAccount (Account *acc, const Account *gain_acct)
{
KvpFrame *cwd;
KvpValue *vvv;
const char * cur_name;
gnc_commodity *acc_comm;
if (!acc || !gain_acct) return;
cwd = xaccAccountGetSlots (acc);
cwd = kvp_frame_get_frame_slash (cwd, "/lot-mgmt/gains-act/");
/* Accounts are indexed by thier unique currency name */
acc_comm = xaccAccountGetCommodity(acc);
cur_name = gnc_commodity_get_unique_name (acc_comm);
xaccAccountBeginEdit (acc);
vvv = kvp_value_new_guid (xaccAccountGetGUID (gain_acct));
kvp_frame_set_slot_nc (cwd, cur_name, vvv);
qof_instance_set_slots(QOF_INSTANCE(acc), acc->inst.kvp_data);
xaccAccountCommitEdit (acc);
}
/* ============================================================== */
Account *
xaccAccountGetDefaultGainAccount (const Account *acc, const gnc_commodity * currency)
{
Account *gain_acct = NULL;
KvpFrame *cwd;
KvpValue *vvv;
GncGUID * gain_acct_guid;
const char * cur_name;
if (!acc || !currency) return NULL;
cwd = xaccAccountGetSlots (acc);
cwd = kvp_frame_get_frame_slash (cwd, "/lot-mgmt/gains-act/");
/* Accounts are indexed by thier unique currency name */
cur_name = gnc_commodity_get_unique_name (currency);
vvv = kvp_frame_get_slot (cwd, cur_name);
gain_acct_guid = kvp_value_get_guid (vvv);
gain_acct = xaccAccountLookup (gain_acct_guid, qof_instance_get_book(acc));
return gain_acct;
}
/* ============================================================== */
/* Functionally identical to the following:
* if (!xaccAccountGetDefaultGainAccount()) {
* xaccAccountSetDefaultGainAccount (); }
* except that it saves a few cycles.
*/
static Account *
GetOrMakeGainAcct (Account *acc, gnc_commodity * currency)
{
Account *gain_acct = NULL;
KvpFrame *cwd;
KvpValue *vvv;
GncGUID * gain_acct_guid;
const char * cur_name;
cwd = xaccAccountGetSlots (acc);
cwd = kvp_frame_get_frame_slash (cwd, "/lot-mgmt/gains-act/");
/* Accounts are indexed by thier unique currency name */
cur_name = gnc_commodity_get_unique_name (currency);
vvv = kvp_frame_get_slot (cwd, cur_name);
gain_acct_guid = kvp_value_get_guid (vvv);
gain_acct = xaccAccountLookup (gain_acct_guid, qof_instance_get_book(acc));
/* If there is no default place to put gains/losses
* for this account, then create such a place */
if (NULL == gain_acct)
{
Account *root;
xaccAccountBeginEdit (acc);
root = gnc_account_get_root(acc);
gain_acct = GetOrMakeLotOrphanAccount (root, currency);
vvv = kvp_value_new_guid (xaccAccountGetGUID (gain_acct));
kvp_frame_set_slot_nc (cwd, cur_name, vvv);
qof_instance_set_slots(QOF_INSTANCE(acc), acc->inst.kvp_data);
xaccAccountCommitEdit (acc);
}
return gain_acct;
}
/* ============================================================== */
Split *
@ -541,22 +397,18 @@ xaccSplitAssignToLot (Split *split, GNCLot *lot)
ts = xaccSplitRetDateReconciledTS (split);
xaccSplitSetDateReconciledTS (new_split, &ts);
/* We do not copy the KVP tree, as it seems like a dangerous
* thing to do. If the user wants to access stuff in the 'old'
* kvp tree from the 'new' split, they shoudl follow the
* 'split-lot' pointers. Yes, this is complicated, but what
* else can one do ??
/* Set the lot-split and peer_guid properties on the two
* splits to indicate that they're linked.
*/
/* Add kvp markup to indicate that these two splits used
* to be one before being 'split'
*/
gnc_kvp_bag_add (split->inst.kvp_data, "lot-split", now,
"peer_guid", xaccSplitGetGUID (new_split),
NULL);
qof_instance_set (QOF_INSTANCE (split),
"lot-split", now,
"peer_guid", xaccSplitGetGUID (new_split),
NULL);
gnc_kvp_bag_add (new_split->inst.kvp_data, "lot-split", now,
"peer_guid", xaccSplitGetGUID (split),
NULL);
qof_instance_set (QOF_INSTANCE (new_split),
"lot-split", now,
"peer_guid", xaccSplitGetGUID (split),
NULL);
xaccAccountInsertSplit (acc, new_split);
xaccTransAppendSplit (trans, new_split);
@ -633,15 +485,14 @@ xaccSplitAssign (Split *split)
Split *
xaccSplitGetCapGainsSplit (const Split *split)
{
KvpValue *val;
GncGUID *gains_guid;
Split *gains_split;
if (!split) return NULL;
val = kvp_frame_get_slot (split->inst.kvp_data, "gains-split");
if (!val) return NULL;
gains_guid = kvp_value_get_guid (val);
qof_instance_get (QOF_INSTANCE (split),
"gains-split", &gains_guid,
NULL);
if (!gains_guid) return NULL;
/* Both splits will be in the same collection, so search there. */
@ -656,15 +507,14 @@ xaccSplitGetCapGainsSplit (const Split *split)
Split *
xaccSplitGetGainsSourceSplit (const Split *split)
{
KvpValue *val;
GncGUID *source_guid;
Split *source_split;
if (!split) return NULL;
val = kvp_frame_get_slot (split->inst.kvp_data, "gains-source");
if (!val) return NULL;
source_guid = kvp_value_get_guid (val);
qof_instance_get (QOF_INSTANCE (split),
"gains-source", &source_guid,
NULL);
if (!source_guid) return NULL;
/* Both splits will be in the same collection, so search there. */
@ -697,8 +547,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
currency = split->parent->common_currency;
ENTER ("(split=%p gains=%p status=0x%x lot=%s)", split,
split->gains_split, split->gains,
kvp_frame_get_string (gnc_lot_get_slots (lot), "/title"));
split->gains_split, split->gains, gnc_lot_get_title(lot));
/* Make sure the status flags and pointers are initialized */
xaccSplitDetermineGainStatus(split);
@ -942,7 +791,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
(FALSE == gnc_commodity_equiv (currency,
xaccAccountGetCommodity(gain_acc))))
{
gain_acc = GetOrMakeGainAcct (lot_acc, currency);
gain_acc = xaccAccountGainsAccount (lot_acc, currency);
}
xaccAccountBeginEdit (gain_acc);
@ -965,17 +814,18 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
xaccSplitSetMemo (lot_split, _("Realized Gain/Loss"));
xaccSplitSetMemo (gain_split, _("Realized Gain/Loss"));
/* For the new transaction, install KVP markup indicating
/* For the new transaction, set the split properties indicating
* that this is the gains transaction that corresponds
* to the gains source.
*/
xaccTransBeginEdit (base_txn);
kvp_frame_set_guid (split->inst.kvp_data, "gains-split",
xaccSplitGetGUID (lot_split));
qof_instance_set_dirty (QOF_INSTANCE (split));
qof_instance_set (QOF_INSTANCE (split),
"gains-split", xaccSplitGetGUID (lot_split),
NULL);
xaccTransCommitEdit (base_txn);
kvp_frame_set_guid (lot_split->inst.kvp_data, "gains-source",
xaccSplitGetGUID (split));
qof_instance_set (QOF_INSTANCE (lot_split),
"gains-source", xaccSplitGetGUID (split),
NULL);
}
else
@ -1031,7 +881,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
xaccSplitSetAmount (gain_split, negvalue);
xaccSplitSetValue (gain_split, negvalue);
/* Some short-cuts to help avoid the above kvp lookup. */
/* Some short-cuts to help avoid the above property lookup. */
split->gains = GAINS_STATUS_CLEAN;
split->gains_split = lot_split;
lot_split->gains = GAINS_STATUS_GAINS;

View File

@ -124,25 +124,6 @@ GNCLot * xaccAccountFindLatestOpenLot (Account *acc,
gnc_numeric sign,
gnc_commodity *currency);
/** The xaccAccountGetDefaultGainAccount() routine will return
* the account to which realized gains/losses may be posted.
* Because gains may be in different currencies, one must
* specify the currency type in which the gains will be posted.
* This routine does nothing more than return the value of
* the "/lot-mgmt/gains-act/XXX" key, where XXX is the unique
* currency name. IOf there is no default account for this
* currency, NULL will be returned.
*/
Account * xaccAccountGetDefaultGainAccount (const Account *acc, const gnc_commodity * currency);
/** The xaccAccountSetDefaultGainAccount() routine can be used
* to set the account to which realized gains/losses will be
* posted by default. This routine does nothing more than set
* value of the "/lot-mgmt/gains-act/XXX" key, where XXX is the
* unique currency name of the currency of gains account.
*/
void xaccAccountSetDefaultGainAccount (Account *acc, const Account *gains_acct);
/** The xaccSplitGetCapGainsSplit() routine returns the split
* that records the cap gains for this split. It returns NULL
* if not found. This routine does nothing more than search for

View File

@ -140,10 +140,18 @@ functions. */
QofSession * qof_session_new (void);
QofBook * qof_session_get_book (QofSession *session);
// TODO: Maybe unroll
void qof_book_kvp_changed (QofBook *book);
/* This horror is to permit the scheme options in
* src/app-utils/options.scm to read and write the book's KVP (another
* horror) directly. It should be refactored into book functions that
* handle the KVP access.
*/
%inline {
KvpFrame *qof_book_get_slots (QofBook *book);
extern KvpFrame *qof_instance_get_slots (QofInstance*);
KvpFrame *qof_book_get_slots (QofBook *book) {
return qof_instance_get_slots (QOF_INSTANCE (book));
}
}
// TODO: Unroll/remove
const char *qof_session_get_url (QofSession *session);
@ -173,7 +181,6 @@ SplitList * qof_query_run_subquery (QofQuery *q, const QofQuery *q);
%include <qofbookslots.h>
%include <qofbook.h>
KvpFrame* qof_book_get_slots(QofBook* book);
%ignore GNC_DENOM_AUTO;
%ignore GNCNumericErrorCodes;
%ignore GNC_ERROR_OK;

View File

@ -22,29 +22,31 @@
* *
\********************************************************************/
#include "config.h"
#include <config.h>
#include <glib.h>
#include <glib/gprintf.h>
#include <glib/gi18n.h>
#include <time.h>
#include "qof.h"
#include "qofbookslots.h"
#include <qof.h>
#include <qofbookslots.h>
#include <gnc-gdate-utils.h>
#include <qofinstance-p.h>
#include "Account.h"
#include "gnc-budget.h"
#include "gnc-commodity.h"
#include "gnc-gdate-utils.h"
static QofLogModule log_module = GNC_MOD_ENGINE;
enum
{
PROP_0,
PROP_NAME,
PROP_DESCRIPTION,
PROP_NUM_PERIODS,
PROP_RECURRENCE,
PROP_NAME, /* Table */
PROP_DESCRIPTION, /* Table */
PROP_NUM_PERIODS, /* Table */
PROP_RUNTIME_0,
PROP_RECURRENCE, /* Cached pointer; Recurrence table holds budget guid */
};
struct budget_s
@ -156,6 +158,9 @@ gnc_budget_set_property( GObject* object,
g_return_if_fail(GNC_IS_BUDGET(object));
budget = GNC_BUDGET(object);
if (prop_id < PROP_RUNTIME_0)
g_assert (qof_instance_get_editlevel(budget));
switch ( prop_id )
{
case PROP_NAME:
@ -626,31 +631,23 @@ gnc_budget_get_default (QofBook *book)
{
QofCollection *col;
GncBudget *bgt = NULL;
kvp_value *kvp_default_budget;
const GncGUID *default_budget_guid;
const GncGUID *default_budget_guid = NULL;
g_return_val_if_fail(book, NULL);
/* See if there is a budget selected in the KVP perferences */
kvp_default_budget = kvp_frame_get_slot_path(qof_book_get_slots (book),
KVP_OPTION_PATH,
OPTION_SECTION_BUDGETING,
OPTION_NAME_DEFAULT_BUDGET,
NULL);
if (kvp_default_budget != NULL )
qof_instance_get (QOF_INSTANCE (book),
"default-budget", &default_budget_guid,
NULL);
if (default_budget_guid != NULL)
{
default_budget_guid = kvp_value_get_guid(kvp_default_budget);
if (default_budget_guid != NULL)
{
col = qof_book_get_collection(book, GNC_ID_BUDGET);
bgt = (GncBudget *) qof_collection_lookup_entity(col,
default_budget_guid);
}
col = qof_book_get_collection(book, GNC_ID_BUDGET);
bgt = (GncBudget *) qof_collection_lookup_entity(col,
default_budget_guid);
}
/* Revert to 2.2.x behavior if there is no defined budget in KVP */
/* Revert to 2.2.x behavior if the book has no default budget. */
if ( bgt == NULL )
{

View File

@ -23,7 +23,7 @@
* *
*******************************************************************/
#include "config.h"
#include <config.h>
#include <glib.h>
#include <glib/gi18n.h>
@ -33,6 +33,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
#include <qofinstance-p.h>
#include "gnc-commodity.h"
#include "gnc-prefs.h"
@ -47,16 +48,16 @@ static QofLogModule log_module = GNC_MOD_COMMODITY;
enum
{
PROP_0,
PROP_NAMESPACE,
PROP_FULL_NAME,
PROP_MNEMONIC,
PROP_PRINTNAME,
PROP_CUSIP,
PROP_FRACTION,
PROP_UNIQUE_NAME,
PROP_QUOTE_FLAG,
PROP_QUOTE_SOURCE,
PROP_QUOTE_TZ,
PROP_NAMESPACE, /* Table */
PROP_FULL_NAME, /* Table */
PROP_MNEMONIC, /* Table */
PROP_PRINTNAME, /* Constructed */
PROP_CUSIP, /* Table */
PROP_FRACTION, /* Table */
PROP_UNIQUE_NAME, /* Constructed */
PROP_QUOTE_FLAG, /* Table */
PROP_QUOTE_SOURCE, /* Table */
PROP_QUOTE_TZ, /* Table */
};
struct gnc_commodity_s
@ -698,6 +699,7 @@ gnc_commodity_set_property (GObject *object,
g_return_if_fail(GNC_IS_COMMODITY(object));
commodity = GNC_COMMODITY(object);
g_assert (qof_instance_get_editlevel(commodity));
switch (prop_id)
{

View File

@ -251,5 +251,16 @@ void gnc_engine_add_commit_error_callback( EngineCommitErrorCallback cb, gpointe
void gnc_engine_signal_commit_error( QofBackendError errcode );
/** STRING CONSTANTS **********************************************
* Used to declare constant KVP keys used in more than one class
*/
#define GNC_INVOICE_ID "gncInvoice"
#define GNC_INVOICE_GUID "invoice-guid"
#define GNC_OWNER_ID "gncOwner"
#define GNC_OWNER_TYPE "owner-type"
#define GNC_OWNER_GUID "owner-guid"
#define GNC_SX_ID "sched-xaction"
#endif
/** @} */

View File

@ -39,10 +39,11 @@
* Copyright (c) 2002,2003 Linas Vepstas <linas@linas.org>
*/
#include "config.h"
#include <config.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <qofinstance-p.h>
#include "Account.h"
#include "AccountP.h"
@ -63,8 +64,15 @@ struct gnc_lot_s
enum
{
PROP_0,
PROP_IS_CLOSED,
PROP_MARKER
// PROP_ACCOUNT, /* Table */
PROP_IS_CLOSED, /* Table */
PROP_INVOICE, /* KVP */
PROP_OWNER_TYPE, /* KVP */
PROP_OWNER_GUID, /* KVP */
PROP_RUNTIME_0,
PROP_MARKER, /* Runtime */
};
typedef struct LotPrivate
@ -93,6 +101,11 @@ typedef struct LotPrivate
/* ============================================================= */
static void gnc_lot_set_invoice (GNCLot* lot, GncGUID *guid);
static GncGUID *gnc_lot_get_invoice (GNCLot* lot);
/* ============================================================= */
/* GObject Initialization */
G_DEFINE_TYPE(GNCLot, gnc_lot, QOF_TYPE_INSTANCE)
@ -125,6 +138,9 @@ gnc_lot_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec*
{
GNCLot* lot;
LotPrivate* priv;
KvpFrame *frame;
gchar *key;
GValue *temp;
g_return_if_fail(GNC_IS_LOT(object));
@ -138,18 +154,41 @@ gnc_lot_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec*
case PROP_MARKER:
g_value_set_int(value, priv->marker);
break;
case PROP_INVOICE:
key = GNC_INVOICE_ID "/" GNC_INVOICE_GUID;
qof_instance_get_kvp (QOF_INSTANCE (lot), key, value);
break;
case PROP_OWNER_TYPE:
key = GNC_OWNER_ID"/" GNC_OWNER_TYPE;
qof_instance_get_kvp (QOF_INSTANCE (lot), key, value);
break;
case PROP_OWNER_GUID:
key = GNC_OWNER_ID "/" GNC_OWNER_GUID;
qof_instance_get_kvp (QOF_INSTANCE (lot), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
gnc_lot_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec)
gnc_lot_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec)
{
GNCLot* lot;
LotPrivate* priv;
KvpFrame *frame;
gchar *key = NULL;
g_return_if_fail(GNC_IS_LOT(object));
lot = GNC_LOT(object);
if (prop_id < PROP_RUNTIME_0)
g_assert (qof_instance_get_editlevel(lot));
priv = GET_PRIVATE(lot);
switch (prop_id)
{
@ -159,7 +198,22 @@ gnc_lot_set_property(GObject* object, guint prop_id, const GValue* value, GParam
case PROP_MARKER:
priv->marker = g_value_get_int(value);
break;
}
case PROP_INVOICE:
key = GNC_INVOICE_ID"/" GNC_INVOICE_GUID;
qof_instance_set_kvp (QOF_INSTANCE (lot), key, value);
break;
case PROP_OWNER_TYPE:
key = GNC_OWNER_ID "/" GNC_OWNER_TYPE;
qof_instance_set_kvp (QOF_INSTANCE (lot), key, value);
break;
case PROP_OWNER_GUID:
key = GNC_OWNER_ID "/" GNC_OWNER_GUID;
qof_instance_set_kvp (QOF_INSTANCE (lot), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
@ -193,8 +247,32 @@ gnc_lot_class_init(GNCLotClass* klass)
0, G_MAXINT8, 0,
G_PARAM_READWRITE));
g_object_class_install_property(
gobject_class,
PROP_INVOICE,
g_param_spec_boxed("invoice",
"Invoice attached to lot",
"Used by GncInvoice",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
g_object_class_install_property(
gobject_class,
PROP_OWNER_TYPE,
g_param_spec_int64("owner-type",
"Owning Entity Type of lot",
"Used by GncOwner",
0, G_MAXINT64, 0,
G_PARAM_READWRITE));
g_object_class_install_property(
gobject_class,
PROP_OWNER_GUID,
g_param_spec_boxed("owner-guid",
"Owner attached to lot",
"Used by GncOwner",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
}
GNCLot *
@ -333,12 +411,6 @@ gnc_lot_set_closed_unknown(GNCLot* lot)
}
}
KvpFrame *
gnc_lot_get_slots (const GNCLot *lot)
{
return qof_instance_get_slots(QOF_INSTANCE(lot));
}
SplitList *
gnc_lot_get_split_list (const GNCLot *lot)
{
@ -363,14 +435,16 @@ const char *
gnc_lot_get_title (const GNCLot *lot)
{
if (!lot) return NULL;
return kvp_frame_get_string (gnc_lot_get_slots(lot), "/title");
return kvp_frame_get_string (qof_instance_get_slots(QOF_INSTANCE (lot)),
"/title");
}
const char *
gnc_lot_get_notes (const GNCLot *lot)
{
if (!lot) return NULL;
return kvp_frame_get_string (gnc_lot_get_slots(lot), "/notes");
return kvp_frame_get_string (qof_instance_get_slots(QOF_INSTANCE (lot)),
"/notes");
}
void
@ -379,7 +453,8 @@ gnc_lot_set_title (GNCLot *lot, const char *str)
if (!lot) return;
qof_begin_edit(QOF_INSTANCE(lot));
qof_instance_set_dirty(QOF_INSTANCE(lot));
kvp_frame_set_str (gnc_lot_get_slots(lot), "/title", str);
kvp_frame_set_str (qof_instance_get_slots(QOF_INSTANCE (lot)),
"/title", str);
gnc_lot_commit_edit(lot);
}
@ -389,7 +464,8 @@ gnc_lot_set_notes (GNCLot *lot, const char *str)
if (!lot) return;
gnc_lot_begin_edit(lot);
qof_instance_set_dirty(QOF_INSTANCE(lot));
kvp_frame_set_str (gnc_lot_get_slots(lot), "/notes", str);
kvp_frame_set_str (qof_instance_get_slots (QOF_INSTANCE (lot)),
"/notes", str);
gnc_lot_commit_edit(lot);
}
@ -675,20 +751,20 @@ gboolean gnc_lot_register (void)
GNCLot * gnc_lot_make_default (Account *acc)
{
GNCLot * lot;
gint64 id;
char buff[200];
gint64 id = 0;
gchar *buff;
lot = gnc_lot_new (qof_instance_get_book(acc));
/* Provide a reasonable title for the new lot */
xaccAccountBeginEdit (acc);
id = kvp_frame_get_gint64 (xaccAccountGetSlots (acc), "/lot-mgmt/next-id");
snprintf (buff, 200, ("%s %" G_GINT64_FORMAT), _("Lot"), id);
kvp_frame_set_str (gnc_lot_get_slots (lot), "/title", buff);
qof_instance_get (QOF_INSTANCE (acc), "lot-next-id", &id, NULL);
buff = g_strdup_printf ("%s %" G_GINT64_FORMAT, _("Lot"), id);
gnc_lot_set_title (lot, buff);
id ++;
kvp_frame_set_gint64 (xaccAccountGetSlots (acc), "/lot-mgmt/next-id", id);
qof_instance_set_dirty (QOF_INSTANCE(acc));
qof_instance_set (QOF_INSTANCE (acc), "lot-next-id", id, NULL);
xaccAccountCommitEdit (acc);
g_free (buff);
return lot;
}

View File

@ -165,11 +165,6 @@ const char * gnc_lot_get_notes (const GNCLot *);
void gnc_lot_set_title (GNCLot *, const char *);
void gnc_lot_set_notes (GNCLot *, const char *);
/** Every lot has a place to hang kvp data. This routine returns that
* place.
* */
KvpFrame * gnc_lot_get_slots (const GNCLot *);
/** XXX: Document? */
GNCLot * gnc_lot_make_default (Account * acc);

View File

@ -41,12 +41,12 @@ static GNCPrice *lookup_nearest_in_time(GNCPriceDB *db, const gnc_commodity *c,
enum
{
PROP_0,
PROP_COMMODITY,
PROP_CURRENCY,
PROP_DATE,
PROP_SOURCE,
PROP_TYPE,
PROP_VALUE
PROP_COMMODITY, /* Table */
PROP_CURRENCY, /* Table */
PROP_DATE, /* Table */
PROP_SOURCE, /* Table */
PROP_TYPE, /* Table */
PROP_VALUE, /* Table, 2 fields (numeric) */
};
/* GObject Initialization */
@ -123,6 +123,8 @@ gnc_price_set_property(GObject* object, guint prop_id, const GValue* value, GPar
g_return_if_fail(GNC_IS_PRICE(object));
price = GNC_PRICE(object);
g_assert (qof_instance_get_editlevel(price));
switch (prop_id)
{
case PROP_SOURCE:

View File

@ -25,9 +25,10 @@
* Author: Derek Atkins <warlord@MIT.EDU>
*/
#include "config.h"
#include <config.h>
#include <glib.h>
#include <qofinstance-p.h>
#include "gncAddress.h"
#include "gncAddressP.h"

View File

@ -26,9 +26,10 @@
* Author: Derek Atkins <warlord@MIT.EDU>
*/
#include "config.h"
#include <config.h>
#include <glib.h>
#include <qofinstance-p.h>
#include "gnc-engine.h"
#include "gncBillTermP.h"
@ -192,6 +193,8 @@ gnc_billterm_set_property (GObject *object,
g_return_if_fail(GNC_IS_BILLTERM(object));
bt = GNC_BILLTERM(object);
g_assert (qof_instance_get_editlevel(bt));
switch (prop_id)
{
case PROP_NAME:

View File

@ -37,6 +37,12 @@
#include <glib.h>
#include "qof.h"
/* KVP key for report PDF directories */
#define OWNER_EXPORT_PDF_DIRNAME "export-pdf-directory"
#define LAST_POSTED_TO_ACCT "last-posted-to-acct"
#define GNC_PAYMENT "payment"
#define GNC_LAST_ACCOUNT "last_acct"
/* @deprecated backwards-compat definitions */
#define GNC_BILLTERM_MODULE_NAME GNC_ID_BILLTERM
#define GNC_CUSTOMER_MODULE_NAME GNC_ID_CUSTOMER

View File

@ -30,6 +30,7 @@
#include <glib.h>
#include <string.h>
#include <qofinstance-p.h>
#include "gnc-commodity.h"
@ -96,7 +97,10 @@ void mark_customer (GncCustomer *customer)
enum
{
PROP_0,
PROP_NAME
PROP_NAME,
PROP_PDF_DIRNAME,
PROP_LAST_POSTED,
PROP_PAYMENT_LAST_ACCT,
};
/* GObject Initialization */
@ -126,7 +130,7 @@ gnc_customer_get_property (GObject *object,
GParamSpec *pspec)
{
GncCustomer *cust;
gchar *key;
g_return_if_fail(GNC_IS_CUSTOMER(object));
cust = GNC_CUSTOMER(object);
@ -135,6 +139,18 @@ gnc_customer_get_property (GObject *object,
case PROP_NAME:
g_value_set_string(value, cust->name);
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_get_kvp (QOF_INSTANCE (cust), key, value);
break;
case PROP_LAST_POSTED:
key = LAST_POSTED_TO_ACCT;
qof_instance_get_kvp (QOF_INSTANCE (cust), key, value);
break;
case PROP_PAYMENT_LAST_ACCT:
key = GNC_PAYMENT "/" GNC_LAST_ACCOUNT;
qof_instance_get_kvp (QOF_INSTANCE (cust), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -144,19 +160,34 @@ gnc_customer_get_property (GObject *object,
static void
gnc_customer_set_property (GObject *object,
guint prop_id,
const GValue *value,
const GValue *value,
GParamSpec *pspec)
{
GncCustomer *cust;
gchar *key;
g_return_if_fail(GNC_IS_CUSTOMER(object));
cust = GNC_CUSTOMER(object);
g_assert (qof_instance_get_editlevel(cust));
switch (prop_id)
{
case PROP_NAME:
gncCustomerSetName(cust, g_value_get_string(value));
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_set_kvp (QOF_INSTANCE (cust), key, value);
break;
case PROP_LAST_POSTED:
key = LAST_POSTED_TO_ACCT;
qof_instance_set_kvp (QOF_INSTANCE (cust), key, value);
break;
case PROP_PAYMENT_LAST_ACCT:
key = GNC_PAYMENT "/" GNC_LAST_ACCOUNT;
qof_instance_set_kvp (QOF_INSTANCE (cust), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -242,6 +273,39 @@ gnc_customer_class_init (GncCustomerClass *klass)
"customer name.",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_PDF_DIRNAME,
g_param_spec_string ("export-pdf-dir",
"Export PDF Directory Name",
"A subdirectory for exporting PDF reports which is "
"appended to the target directory when writing them "
"out. It is retrieved from preferences and stored on "
"each 'Owner' object which prints items after "
"printing.",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property(
gobject_class,
PROP_LAST_POSTED,
g_param_spec_boxed("invoice-last-posted-account",
"Invoice Last Posted Account",
"The last account to which an invoice belonging to "
"this owner was posted.",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
g_object_class_install_property(
gobject_class,
PROP_PAYMENT_LAST_ACCT,
g_param_spec_boxed("payment-last-account",
"Payment Last Account",
"The last account to which an payment belonging to "
"this owner was posted.",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
}
/* Create/Destroy Functions */
@ -866,7 +930,6 @@ gboolean gncCustomerRegister (void)
(QofSetterFunc)gncCustomerSetTaxTableOverride
},
{ CUSTOMER_TERMS, GNC_ID_BILLTERM, (QofAccessFunc)gncCustomerGetTerms, (QofSetterFunc)gncCustomerSetTerms },
{ CUSTOMER_SLOTS, QOF_TYPE_KVP, (QofAccessFunc)qof_instance_get_slots, NULL },
{ QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncCustomerGetActive, (QofSetterFunc)gncCustomerSetActive },
{ QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
{ QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },

View File

@ -26,10 +26,11 @@
* Author: Derek Atkins <warlord@MIT.EDU>
*/
#include "config.h"
#include <config.h>
#include <glib.h>
#include <string.h>
#include <qofinstance-p.h>
#include "Account.h"
#include "gnc-commodity.h"
@ -79,16 +80,19 @@ void mark_employee (GncEmployee *employee)
enum
{
PROP_0,
PROP_USERNAME,
PROP_ID,
PROP_ACTIVE,
PROP_LANGUAGE,
PROP_CURRENCY,
PROP_ACL,
PROP_ADDRESS,
PROP_WORKDAY,
PROP_RATE,
PROP_CCARD
PROP_USERNAME, /* Table */
PROP_ID, /* Table */
PROP_LANGUAGE, /* Table */
PROP_ACL, /* Table */
PROP_ACTIVE, /* Table */
PROP_CURRENCY, /* Table */
PROP_CCARD, /* Table */
PROP_WORKDAY, /* Table (numeric) */
PROP_RATE, /* Table (numeric) */
PROP_ADDRESS, /* Table, 8 fields */
PROP_PDF_DIRNAME, /* KVP */
PROP_LAST_POSTED, /* KVP */
PROP_PAYMENT_LAST_ACCT, /* KVP */
};
/* GObject Initialization */
@ -124,6 +128,7 @@ gnc_employee_get_property (GObject *object,
GParamSpec *pspec)
{
GncEmployee *emp;
gchar *key;
g_return_if_fail(GNC_IS_EMPLOYEE(object));
@ -160,6 +165,18 @@ gnc_employee_get_property (GObject *object,
case PROP_CCARD:
g_value_take_object(value, emp->ccard_acc);
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_get_kvp (QOF_INSTANCE (emp), key, value);
break;
case PROP_LAST_POSTED:
key = LAST_POSTED_TO_ACCT;
qof_instance_get_kvp (QOF_INSTANCE (emp), key, value);
break;
case PROP_PAYMENT_LAST_ACCT:
key = GNC_PAYMENT "/" GNC_LAST_ACCOUNT;
qof_instance_get_kvp (QOF_INSTANCE (emp), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -173,10 +190,13 @@ gnc_employee_set_property (GObject *object,
GParamSpec *pspec)
{
GncEmployee *emp;
gchar *key;
g_return_if_fail(GNC_IS_EMPLOYEE(object));
emp = GNC_EMPLOYEE(object);
g_assert (qof_instance_get_editlevel(emp));
switch (prop_id)
{
case PROP_USERNAME:
@ -209,6 +229,18 @@ gnc_employee_set_property (GObject *object,
case PROP_CCARD:
gncEmployeeSetCCard(emp, g_value_get_object(value));
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_set_kvp (QOF_INSTANCE (emp), key, value);
break;
case PROP_LAST_POSTED:
key = LAST_POSTED_TO_ACCT;
qof_instance_set_kvp (QOF_INSTANCE (emp), key, value);
break;
case PROP_PAYMENT_LAST_ACCT:
key = GNC_PAYMENT "/" GNC_LAST_ACCOUNT;
qof_instance_set_kvp (QOF_INSTANCE (emp), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -367,6 +399,39 @@ gnc_employee_class_init (GncEmployeeClass *klass)
"The credit card account for this employee.",
GNC_TYPE_ACCOUNT,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_PDF_DIRNAME,
g_param_spec_string ("export-pdf-dir",
"Export PDF Directory Name",
"A subdirectory for exporting PDF reports which is "
"appended to the target directory when writing them "
"out. It is retrieved from preferences and stored on "
"each 'Owner' object which prints items after "
"printing.",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property(
gobject_class,
PROP_LAST_POSTED,
g_param_spec_boxed("invoice-last-posted-account",
"Invoice Last Posted Account",
"The last account to which an invoice belonging to "
"this owner was posted.",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
g_object_class_install_property(
gobject_class,
PROP_PAYMENT_LAST_ACCT,
g_param_spec_boxed("payment-last-account",
"Payment Last Account",
"The last account to which an payment belonging to "
"this owner was posted.",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
}
/* Create/Destroy Functions */

View File

@ -25,9 +25,10 @@
* Author: Derek Atkins <warlord@MIT.EDU>
*/
#include "config.h"
#include <config.h>
#include <glib.h>
#include <qofinstance-p.h>
#include "gnc-commodity.h"
@ -211,7 +212,32 @@ void mark_entry (GncEntry *entry)
enum
{
PROP_0,
PROP_DESCRIPTION
// PROP_DATE, /* Table */
// PROP_DATE_ENTERED, /* Table */
PROP_DESCRIPTION, /* Table */
// PROP_ACTION, /* Table */
// PROP_NOTES, /* Table */
// PROP_QUANTITY, /* Table (numeric) */
// PROP_I_ACCT, /* Table */
// PROP_I_PRICE, /* Table (numeric) */
// PROP_I_DISCOUNT, /* Table (numeric) */
// PROP_INVOICE, /* Table */
// PROP_I_DISC_TYPE, /* Table */
// PROP_I_DISC_HOW, /* Table */
// PROP_I_TAXABLE, /* Table */
// PROP_I_TAX_INCL, /* Table */
// PROP_I_TAXTABLE, /* Table */
// PROP_B_ACCT, /* Table */
// PROP_B_PRICE, /* Table (numeric) */
// PROP_BILL, /* Table */
// PROP_B_TAXTABLE_1, /* Table */
// PROP_B_TAX_INCL, /* Table */
// PROP_B_TAXTABLE, /* Table */
// PROP_B_PAYTYPE, /* Table */
// PROP_BILLABLE, /* Table */
// PROP_BILLTO_TYPE, /* Table */
// PROP_BILLTO, /* Table */
// PROP_ORDER, /* Table */
};
/* GObject Initialization */
@ -267,6 +293,8 @@ gnc_entry_set_property (GObject *object,
g_return_if_fail(GNC_IS_ENTRY(object));
entry = GNC_ENTRY(object);
g_assert (qof_instance_get_editlevel(entry));
switch (prop_id)
{
case PROP_DESCRIPTION:

View File

@ -27,10 +27,11 @@
* Author: Derek Atkins <warlord@MIT.EDU>
*/
#include "config.h"
#include <config.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <qofinstance-p.h>
#include "Transaction.h"
#include "Account.h"
@ -81,8 +82,6 @@ static QofLogModule log_module = GNC_MOD_BUSINESS;
#define _GNC_MOD_NAME GNC_ID_INVOICE
#define GNC_INVOICE_ID "gncInvoice"
#define GNC_INVOICE_GUID "invoice-guid"
#define GNC_INVOICE_IS_CN "credit-note"
#define SET_STR(obj, member, str) { \
@ -113,7 +112,22 @@ QofBook * gncInvoiceGetBook(GncInvoice *x)
enum
{
PROP_0,
PROP_NOTES
// PROP_ID, /* Table */
// PROP_DATE_OPENED, /* Table */
// PROP_DATE_POSTED, /* Table */
PROP_NOTES, /* Table */
// PROP_ACTIVE, /* Table */
// PROP_CURRENCY, /* Table */
// PROP_OWNER_TYPE, /* Table */
// PROP_OWNER, /* Table */
// PROP_TERMS, /* Table */
// PROP_BILLING_ID, /* Table */
// PROP_POST_TXN, /* Table */
// PROP_POST_LOT, /* Table */
// PROP_POST_ACCOUNT, /* Table */
// PROP_BILLTO_TYPE, /* Table */
// PROP_BILLTO, /* Table */
// PROP_CHARGE_AMOUNT, /* Table, (numeric) */
};
/* GObject Initialization */
@ -169,6 +183,8 @@ gnc_invoice_set_property (GObject *object,
g_return_if_fail(GNC_IS_INVOICE(object));
inv = GNC_INVOICE(object);
g_assert (qof_instance_get_editlevel(inv));
switch (prop_id)
{
case PROP_NOTES:
@ -1133,52 +1149,37 @@ qofInvoiceSetJob (GncInvoice *invoice, GncJob *job)
static void
gncInvoiceDetachFromLot (GNCLot *lot)
{
KvpFrame *kvp;
if (!lot) return;
gnc_lot_begin_edit (lot);
kvp = gnc_lot_get_slots (lot);
kvp_frame_set_slot_path (kvp, NULL, GNC_INVOICE_ID, GNC_INVOICE_GUID, NULL);
qof_instance_set_dirty (QOF_INSTANCE (lot));
qof_instance_set (QOF_INSTANCE (lot), "invoice", NULL, NULL);
gnc_lot_commit_edit (lot);
}
static void
gncInvoiceAttachToLot (GncInvoice *invoice, GNCLot *lot)
{
KvpFrame *kvp;
KvpValue *value;
GncGUID *guid;
if (!invoice || !lot)
return;
if (invoice->posted_lot) return; /* Cannot reset invoice's lot */
guid = (GncGUID*)qof_instance_get_guid (QOF_INSTANCE (invoice));
gnc_lot_begin_edit (lot);
kvp = gnc_lot_get_slots (lot);
value = kvp_value_new_guid (qof_instance_get_guid (QOF_INSTANCE(invoice)));
kvp_frame_set_slot_path (kvp, value, GNC_INVOICE_ID, GNC_INVOICE_GUID, NULL);
qof_instance_set_dirty (QOF_INSTANCE (lot));
qof_instance_set (QOF_INSTANCE (lot), "invoice", guid, NULL);
gnc_lot_commit_edit (lot);
kvp_value_delete (value);
gncInvoiceSetPostedLot (invoice, lot);
}
GncInvoice * gncInvoiceGetInvoiceFromLot (GNCLot *lot)
{
KvpFrame *kvp;
KvpValue *value;
GncGUID *guid;
GncGUID *guid = NULL;
QofBook *book;
if (!lot) return NULL;
book = gnc_lot_get_book (lot);
kvp = gnc_lot_get_slots (lot);
value = kvp_frame_get_slot_path (kvp, GNC_INVOICE_ID, GNC_INVOICE_GUID, NULL);
if (!value) return NULL;
guid = kvp_value_get_guid (value);
qof_instance_get (QOF_INSTANCE (lot), "invoice", &guid, NULL);
return gncInvoiceLookup(book, guid);
}
@ -1194,10 +1195,8 @@ gncInvoiceAttachToTxn (GncInvoice *invoice, Transaction *txn)
if (invoice->posted_txn) return; /* Cannot reset invoice's txn */
xaccTransBeginEdit (txn);
kvp = xaccTransGetSlots (txn);
value = kvp_value_new_guid (qof_instance_get_guid(QOF_INSTANCE(invoice)));
kvp_frame_set_slot_path (kvp, value, GNC_INVOICE_ID, GNC_INVOICE_GUID, NULL);
kvp_value_delete (value);
qof_instance_set (QOF_INSTANCE (txn), "invoice",
qof_instance_get_guid (QOF_INSTANCE (invoice)), NULL);
xaccTransSetTxnType (txn, TXN_TYPE_INVOICE);
xaccTransCommitEdit (txn);
gncInvoiceSetPostedTxn (invoice, txn);
@ -1206,19 +1205,13 @@ gncInvoiceAttachToTxn (GncInvoice *invoice, Transaction *txn)
GncInvoice *
gncInvoiceGetInvoiceFromTxn (const Transaction *txn)
{
KvpFrame *kvp;
KvpValue *value;
GncGUID *guid;
GncGUID *guid = NULL;
QofBook *book;
if (!txn) return NULL;
book = xaccTransGetBook (txn);
kvp = xaccTransGetSlots (txn);
value = kvp_frame_get_slot_path (kvp, GNC_INVOICE_ID, GNC_INVOICE_GUID, NULL);
if (!value) return NULL;
guid = kvp_value_get_guid (value);
qof_instance_get (QOF_INSTANCE (txn), "invoice", &guid, NULL);
return gncInvoiceLookup(book, guid);
}

View File

@ -268,6 +268,7 @@ GncInvoice * gncInvoiceGetInvoiceFromLot (GNCLot *lot);
*/
static inline GncInvoice * gncInvoiceLookup (const QofBook *book, const GncGUID *guid)
{
if (book == NULL || guid == NULL) return NULL;
QOF_BOOK_RETURN_ENTITY(book, guid, GNC_ID_INVOICE, GncInvoice);
}
@ -305,7 +306,6 @@ QofBook *gncInvoiceGetBook(GncInvoice *x);
/** deprecated functions */
#define gncInvoiceGetGUID(x) qof_instance_get_guid(QOF_INSTANCE(x))
#define gncInvoiceRetGUID(x) (x ? *(qof_instance_get_guid(QOF_INSTANCE(x))) : *(guid_null()))
#define gncInvoiceLookupDirect(G,B) gncInvoiceLookup((B),&(G))
/** Test support function used by test-dbi-business-stuff.c */
gboolean gncInvoiceEqual(const GncInvoice *a, const GncInvoice *b);

View File

@ -26,10 +26,11 @@
* Author: Derek Atkins <warlord@MIT.EDU>
*/
#include "config.h"
#include <config.h>
#include <glib.h>
#include <string.h>
#include <qofinstance-p.h>
#include "gnc-features.h"
#include "gncInvoice.h"
@ -71,7 +72,13 @@ void mark_job (GncJob *job)
enum
{
PROP_0,
PROP_NAME
// PROP_ID, /* Table */
PROP_NAME, /* Table */
// PROP_REFERENCE, /* Table */
// PROP_ACTIVE, /* Table */
// PROP_OWNER_TYPE, /* Table */
// PROP_OWNER, /* Table */
PROP_PDF_DIRNAME, /* KVP */
};
/* GObject Initialization */
@ -101,6 +108,7 @@ gnc_job_get_property (GObject *object,
GParamSpec *pspec)
{
GncJob *job;
gchar *key;
g_return_if_fail(GNC_IS_JOB(object));
@ -110,6 +118,10 @@ gnc_job_get_property (GObject *object,
case PROP_NAME:
g_value_set_string(value, job->name);
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_get_kvp (QOF_INSTANCE (job), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -123,15 +135,22 @@ gnc_job_set_property (GObject *object,
GParamSpec *pspec)
{
GncJob *job;
gchar *key;
g_return_if_fail(GNC_IS_JOB(object));
job = GNC_JOB(object);
g_assert (qof_instance_get_editlevel(job));
switch (prop_id)
{
case PROP_NAME:
gncJobSetName(job, g_value_get_string(value));
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_set_kvp (QOF_INSTANCE (job), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -177,6 +196,19 @@ gnc_job_class_init (GncJobClass *klass)
"by the GUI as the job mnemonic.",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_PDF_DIRNAME,
g_param_spec_string ("export-pdf-dir",
"Export PDF Directory Name",
"A subdirectory for exporting PDF reports which is "
"appended to the target directory when writing them "
"out. It is retrieved from preferences and stored on "
"each 'Owner' object which prints items after "
"printing.",
NULL,
G_PARAM_READWRITE));
}
/* Create/Destroy Functions */

View File

@ -25,10 +25,11 @@
* Author: Derek Atkins <warlord@MIT.EDU>
*/
#include "config.h"
#include <config.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <qofinstance-p.h>
#include "gncEntry.h"
#include "gncEntryP.h"
@ -84,12 +85,14 @@ void mark_order (GncOrder *order)
enum
{
PROP_0,
PROP_ID,
PROP_NOTES,
PROP_ACTIVE,
PROP_DATE_OPENED,
PROP_DATE_CLOSED,
PROP_REFERENCE
PROP_ID, /* Table */
PROP_NOTES, /* Table */
PROP_REFERENCE, /* Table */
PROP_ACTIVE, /* Table */
PROP_DATE_OPENED, /* Table */
PROP_DATE_CLOSED, /* Table */
// PROP_OWNER_TYPE, /* Table */
// PROP_OWNER, /* Table */
};
/* GObject Initialization */
@ -160,6 +163,8 @@ gnc_order_set_property (GObject *object,
g_return_if_fail(GNC_IS_ORDER(object));
order = GNC_ORDER(object);
g_assert (qof_instance_get_editlevel(order));
switch (prop_id)
{
case PROP_ID:

View File

@ -29,11 +29,12 @@
* Author: Derek Atkins <warlord@MIT.EDU>
*/
#include "config.h"
#include <config.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <string.h> /* for memcpy() */
#include <qofinstance-p.h>
#include "gncCustomerP.h"
#include "gncEmployeeP.h"
@ -50,8 +51,6 @@
#define _GNC_MOD_NAME GNC_ID_OWNER
#define GNC_OWNER_ID "gncOwner"
#define GNC_OWNER_TYPE "owner-type"
#define GNC_OWNER_GUID "owner-guid"
GncOwner * gncOwnerNew (void)
{
@ -99,6 +98,36 @@ void gncOwnerBeginEdit (GncOwner *owner)
}
}
void gncOwnerCommitEdit (GncOwner *owner)
{
if (!owner) return;
switch (owner->type)
{
case GNC_OWNER_NONE :
case GNC_OWNER_UNDEFINED :
break;
case GNC_OWNER_CUSTOMER :
{
gncCustomerCommitEdit(owner->owner.customer);
break;
}
case GNC_OWNER_JOB :
{
gncJobCommitEdit(owner->owner.job);
break;
}
case GNC_OWNER_VENDOR :
{
gncVendorCommitEdit(owner->owner.vendor);
break;
}
case GNC_OWNER_EMPLOYEE :
{
gncEmployeeCommitEdit(owner->owner.employee);
break;
}
}
}
void gncOwnerDestroy (GncOwner *owner)
{
@ -567,52 +596,31 @@ const GncGUID * gncOwnerGetEndGUID (const GncOwner *owner)
void gncOwnerAttachToLot (const GncOwner *owner, GNCLot *lot)
{
KvpFrame *kvp;
KvpValue *value;
if (!owner || !lot)
if (!owner || !lot)
return;
kvp = gnc_lot_get_slots (lot);
gnc_lot_begin_edit (lot);
value = kvp_value_new_gint64 (gncOwnerGetType (owner));
kvp_frame_set_slot_path (kvp, value, GNC_OWNER_ID, GNC_OWNER_TYPE, NULL);
kvp_value_delete (value);
value = kvp_value_new_guid (gncOwnerGetGUID (owner));
kvp_frame_set_slot_path (kvp, value, GNC_OWNER_ID, GNC_OWNER_GUID, NULL);
qof_instance_set_dirty (QOF_INSTANCE (lot));
qof_instance_set (QOF_INSTANCE (lot),
"owner-type", (gint64)gncOwnerGetType (owner),
"owner-guid", gncOwnerGetGUID (owner),
NULL);
gnc_lot_commit_edit (lot);
kvp_value_delete (value);
}
gboolean gncOwnerGetOwnerFromLot (GNCLot *lot, GncOwner *owner)
{
KvpFrame *kvp;
KvpValue *value;
GncGUID *guid;
GncGUID *guid = NULL;
QofBook *book;
GncOwnerType type;
GncOwnerType type = GNC_OWNER_NONE;
if (!lot || !owner) return FALSE;
book = gnc_lot_get_book (lot);
kvp = gnc_lot_get_slots (lot);
value = kvp_frame_get_slot_path (kvp, GNC_OWNER_ID, GNC_OWNER_TYPE, NULL);
if (!value) return FALSE;
type = kvp_value_get_gint64 (value);
value = kvp_frame_get_slot_path (kvp, GNC_OWNER_ID, GNC_OWNER_GUID, NULL);
if (!value) return FALSE;
guid = kvp_value_get_guid (value);
if (!guid)
return FALSE;
qof_instance_get (QOF_INSTANCE (lot),
"owner-type", &type,
"owner-guid", &guid,
NULL);
switch (type)
{
case GNC_OWNER_CUSTOMER:
@ -640,23 +648,6 @@ gboolean gncOwnerIsValid (const GncOwner *owner)
return (owner->owner.undefined != NULL);
}
KvpFrame* gncOwnerGetSlots(GncOwner* owner)
{
if (!owner) return NULL;
switch (gncOwnerGetType(owner))
{
case GNC_OWNER_CUSTOMER:
case GNC_OWNER_VENDOR:
case GNC_OWNER_EMPLOYEE:
return qof_instance_get_slots(QOF_INSTANCE(owner->owner.undefined));
case GNC_OWNER_JOB:
return gncOwnerGetSlots(gncJobGetOwner(gncOwnerGetJob(owner)));
default:
return NULL;
}
}
gboolean
gncOwnerLotMatchOwnerFunc (GNCLot *lot, gpointer user_data)
{

View File

@ -197,9 +197,6 @@ gboolean gncOwnerGetOwnerFromLot (GNCLot *lot, GncOwner *owner);
gboolean gncOwnerGetOwnerFromTypeGuid (QofBook *book, GncOwner *owner, QofIdType type, GncGUID *guid);
/** Get the kvp-frame from the underlying owner object */
KvpFrame* gncOwnerGetSlots(GncOwner* owner);
/**
* Create a lot for a payment to the owner using the other
* parameters passed in. If a transaction is set, this transaction will be
@ -307,6 +304,7 @@ void gncOwnerFree (GncOwner *owner);
* without knowing its type.
*/
void gncOwnerBeginEdit (GncOwner *owner);
void gncOwnerCommitEdit (GncOwner *owner);
void gncOwnerDestroy (GncOwner *owner);
#endif /* GNC_OWNER_H_ */

View File

@ -26,9 +26,10 @@
* Author: Derek Atkins <warlord@MIT.EDU>
*/
#include "config.h"
#include <config.h>
#include <glib.h>
#include <qofinstance-p.h>
#include "gnc-features.h"
#include "gncTaxTableP.h"
@ -208,9 +209,10 @@ gncTaxTableRemoveChild (GncTaxTable *table, const GncTaxTable *child)
enum
{
PROP_0,
PROP_NAME,
PROP_INVISIBLE,
PROP_REFCOUNT
PROP_NAME, /* Table */
PROP_INVISIBLE, /* Table */
PROP_REFCOUNT, /* Table */
// PROP_PARENT, /* Table */
};
/* GObject Initialization */
@ -272,6 +274,8 @@ gnc_taxtable_set_property (GObject *object,
g_return_if_fail(GNC_IS_TAXTABLE(object));
tt = GNC_TAXTABLE(object);
g_assert (qof_instance_get_editlevel(tt));
switch (prop_id)
{
case PROP_NAME:

View File

@ -26,10 +26,11 @@
* Author: Derek Atkins <warlord@MIT.EDU>
*/
#include "config.h"
#include <config.h>
#include <glib.h>
#include <string.h>
#include <qofinstance-p.h>
#include "gnc-commodity.h"
#include "gncAddressP.h"
@ -88,17 +89,20 @@ void mark_vendor (GncVendor *vendor)
enum
{
PROP_0,
PROP_NAME,
PROP_ID,
PROP_NOTES,
PROP_CURRENCY,
PROP_ACTIVE,
PROP_TAXTABLE_OVERRIDE,
PROP_BILLTERMS,
PROP_TAXTABLE,
PROP_ADDRESS,
PROP_TAX_INCLUDED,
PROP_TAX_INCLUDED_STR
PROP_NAME, /* Table */
PROP_ID, /* Table */
PROP_NOTES, /* Table */
PROP_CURRENCY, /* Table */
PROP_ACTIVE, /* Table */
PROP_TAXTABLE_OVERRIDE, /* Table */
PROP_BILLTERMS, /* Table */
PROP_TAXTABLE, /* Table */
PROP_ADDRESS, /* Table, 8 fields */
PROP_TAX_INCLUDED, /* Table */
PROP_TAX_INCLUDED_STR, /* Alternate setter for PROP_TAX_INCLUDED */
PROP_PDF_DIRNAME, /* KVP */
PROP_LAST_POSTED, /* KVP */
PROP_PAYMENT_LAST_ACCT, /* KVP */
};
/* GObject Initialization */
@ -134,6 +138,7 @@ gnc_vendor_get_property (GObject *object,
GParamSpec *pspec)
{
GncVendor *vendor;
gchar *key;
g_return_if_fail(GNC_IS_VENDOR(object));
@ -173,6 +178,18 @@ gnc_vendor_get_property (GObject *object,
case PROP_TAX_INCLUDED_STR:
g_value_set_string(value, qofVendorGetTaxIncluded(vendor));
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_get_kvp (QOF_INSTANCE (vendor), key, value);
break;
case PROP_LAST_POSTED:
key = LAST_POSTED_TO_ACCT;
qof_instance_get_kvp (QOF_INSTANCE (vendor), key, value);
break;
case PROP_PAYMENT_LAST_ACCT:
key = GNC_PAYMENT "/" GNC_LAST_ACCOUNT;
qof_instance_get_kvp (QOF_INSTANCE (vendor), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -186,10 +203,13 @@ gnc_vendor_set_property (GObject *object,
GParamSpec *pspec)
{
GncVendor *vendor;
gchar *key;
g_return_if_fail(GNC_IS_VENDOR(object));
vendor = GNC_VENDOR(object);
g_assert (qof_instance_get_editlevel(vendor));
switch (prop_id)
{
case PROP_NAME:
@ -225,6 +245,18 @@ gnc_vendor_set_property (GObject *object,
case PROP_TAX_INCLUDED_STR:
qofVendorSetTaxIncluded(vendor, g_value_get_string(value));
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_set_kvp (QOF_INSTANCE (vendor), key, value);
break;
case PROP_LAST_POSTED:
key = LAST_POSTED_TO_ACCT;
qof_instance_set_kvp (QOF_INSTANCE (vendor), key, value);
break;
case PROP_PAYMENT_LAST_ACCT:
key = GNC_PAYMENT "/" GNC_LAST_ACCOUNT;
qof_instance_set_kvp (QOF_INSTANCE (vendor), key, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -390,6 +422,38 @@ gnc_vendor_class_init (GncVendorClass *klass)
"The tax-included-string property contains a character version of tax-included.",
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property
(gobject_class,
PROP_PDF_DIRNAME,
g_param_spec_string ("export-pdf-dir",
"Export PDF Directory Name",
"A subdirectory for exporting PDF reports which is "
"appended to the target directory when writing them "
"out. It is retrieved from preferences and stored on "
"each 'Owner' object which prints items after "
"printing.",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property(
gobject_class,
PROP_LAST_POSTED,
g_param_spec_boxed("invoice-last-posted-account",
"Invoice Last Posted Account",
"The last account to which an invoice belonging to "
"this owner was posted.",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
g_object_class_install_property(
gobject_class,
PROP_PAYMENT_LAST_ACCT,
g_param_spec_boxed("payment-last-account",
"Payment Last Account",
"The last account to which an payment belonging to "
"this owner was posted.",
GNC_TYPE_GUID,
G_PARAM_READWRITE));
}
/* Create/Destroy Functions */

View File

@ -26,6 +26,7 @@
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <qofinstance-p.h>
#include "Account.h"
#include "AccountP.h"
@ -1339,7 +1340,7 @@ get_random_split(QofBook *book, Account *acct, Transaction *trn)
else
g_assert(!gnc_numeric_positive_p(amt)); /* non-positive amt */
xaccSplitSetSlots_nc(ret, get_random_kvp_frame());
qof_instance_set_slots(QOF_INSTANCE (ret), get_random_kvp_frame());
xaccTransCommitEdit(trn);
return ret;
@ -1366,7 +1367,7 @@ make_random_changes_to_split (Split *split)
xaccSplitSetDateReconciledTS (split, ts);
g_free(ts);
xaccSplitSetSlots_nc (split, get_random_kvp_frame());
qof_instance_set_slots (QOF_INSTANCE (split), get_random_kvp_frame());
/* Don't change share values/prices here, since that would
* throw transactions out of balance. Do that in the corresponding
@ -2169,13 +2170,13 @@ make_trans_query (Transaction *trans, TestQueryTypes query_types)
}
if (query_types & SPLIT_KVP_QT)
add_kvp_query (q, xaccSplitGetSlots (s), GNC_ID_SPLIT);
add_kvp_query (q, qof_instance_get_slots (QOF_INSTANCE (s)), GNC_ID_SPLIT);
if (query_types & TRANS_KVP_QT)
add_kvp_query (q, xaccTransGetSlots (trans), GNC_ID_TRANS);
add_kvp_query (q, qof_instance_get_slots (QOF_INSTANCE (trans)), GNC_ID_TRANS);
if (query_types & ACCOUNT_KVP_QT)
add_kvp_query (q, xaccAccountGetSlots (a), GNC_ID_ACCOUNT);
add_kvp_query (q, qof_instance_get_slots (QOF_INSTANCE (a)), GNC_ID_ACCOUNT);
return q;
}

View File

@ -116,6 +116,7 @@ test_engine_SOURCES = \
utest-Account.c \
utest-Budget.c \
utest-Invoice.c \
test-engine-kvp-properties.c \
dummy.cpp
test_engine_LDADD = \

View File

@ -33,6 +33,7 @@
#include "cashobjects.h"
#include "test-stuff.h"
#include "test-engine-stuff.h"
#include <qofinstance-p.h>
static void
run_test (void)
@ -61,7 +62,9 @@ run_test (void)
/*****/
five = gnc_numeric_create(5, 1);
qof_instance_increase_editlevel (acc);
g_object_set(acc, "start-balance", &five, NULL);
qof_instance_decrease_editlevel (acc);
xaccAccountRecomputeBalance(acc);
g_object_get(acc, "start-balance", &start, "end-balance", &end, NULL);
end2 = xaccAccountGetBalance(acc);

View File

@ -24,9 +24,11 @@
*
*********************************************************************/
#include "config.h"
#include <config.h>
#include <glib.h>
#include "qof.h"
#include <qof.h>
#include <qofinstance-p.h>
#include "cashobjects.h"
#include "gncCustomerP.h"
#include "gncInvoiceP.h"

View File

@ -24,9 +24,11 @@
*
*********************************************************************/
#include "config.h"
#include <config.h>
#include <glib.h>
#include "qof.h"
#include <qof.h>
#include <qofinstance-p.h>
#include "gncEmployeeP.h"
#include "gncCustomerP.h"
#include "gncJobP.h"

View File

@ -0,0 +1,458 @@
/********************************************************************
* test-engine-kvp-properties.c: GLib g_test test suite for *
* KVP-based properties in several engine classes. *
* Copyright 2013 John Ralls <jralls@ceridwen.us> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
* Boston, MA 02110-1301, USA gnu@gnu.org *
\********************************************************************/
/**
* Test Engine KVP Properties Acceptance testing for KVP Properties
* added to various engine classes to make private the internals of
* KVP storage used for a variety of parameters on several engine
* classes.
*/
#include <config.h>
#include <glib.h>
#include <qof.h>
#include <unittest-support.h>
#include "../Transaction.h"
#include "../Split.h"
#include "../Account.h"
#include "../SchedXAction.h"
#include "../gncCustomer.h"
#include "../gncEmployee.h"
#include "../gncJob.h"
#include "../gncVendor.h"
typedef struct
{
union
{
Account *acct;
Transaction *trans;
Split *split;
GNCLot *lot;
GncCustomer *cust;
GncEmployee *emp;
GncJob *job;
GncVendor *vend;
};
GSList *hdlrs;
} Fixture;
/* Prototype to shut clang up */
void test_suite_engine_kvp_properties (void);
/* Private QofInstance functions needed for testing */
extern void qof_instance_mark_clean (QofInstance*);
const gchar *suitename = "/engine/kvp-properties";
static void
setup_account (Fixture *fixture, gconstpointer pData)
{
QofBook *book = qof_book_new ();
fixture->acct = xaccMallocAccount (book);
}
static void
setup_trans (Fixture *fixture, gconstpointer pData)
{
QofBook *book = qof_book_new ();
fixture->trans = xaccMallocTransaction (book);
}
static void
setup_split (Fixture *fixture, gconstpointer pData)
{
QofBook *book = qof_book_new ();
fixture->split = xaccMallocSplit (book);
}
static void
setup_lot (Fixture *fixture, gconstpointer pData)
{
QofBook *book = qof_book_new ();
fixture->lot = gnc_lot_new (book);
}
static void
setup_customer (Fixture *fixture, gconstpointer pData)
{
QofBook *book = qof_book_new ();
fixture->cust = gncCustomerCreate (book);
}
static void
setup_employee (Fixture *fixture, gconstpointer pData)
{
QofBook *book = qof_book_new ();
fixture->emp = gncEmployeeCreate (book);
}
static void
setup_job (Fixture *fixture, gconstpointer pData)
{
QofBook *book = qof_book_new ();
fixture->job = gncJobCreate (book);
}
static void
setup_vendor (Fixture *fixture, gconstpointer pData)
{
QofBook *book = qof_book_new ();
fixture->vend = gncVendorCreate (book);
}
static void
teardown (Fixture *fixture, gconstpointer pData)
{
/* It doesn't actually matter which union member we use here, they're
* all QofInstances, so this will work for any of them.
*/
QofBook *book = qof_instance_get_book (QOF_INSTANCE (fixture->acct));
test_destroy (fixture->acct);
test_destroy (book);
}
static void
test_account_kvp_properties (Fixture *fixture, gconstpointer pData)
{
gint64 next_id = 12345678909876;
gint64 ab_acct_uid = 67890987654321;
gint64 next_id_r, ab_acct_uid_r;
gchar *online_id = "my online id";
gchar *ab_acct_id = "1234-5678-9087";
gchar *ab_bank_code = "0032340";
gchar *online_id_r, *ab_acct_id_r, *ab_bank_code_r;
GncGUID *ofx_income_acct = guid_malloc ();
GncGUID *ofx_income_acct_r;
Timespec trans_retr = timespec_now ();
Timespec *trans_retr_r;
xaccAccountBeginEdit (fixture->acct);
qof_instance_set (QOF_INSTANCE (fixture->acct),
"lot-next-id", next_id,
"online-id", online_id,
"ofx-income-account", ofx_income_acct,
"ab-account-id", ab_acct_id,
"ab-bank-code", ab_bank_code,
"ab-account-uid", ab_acct_uid,
"ab-trans-retrieval", &trans_retr,
NULL);
g_assert (qof_instance_is_dirty (QOF_INSTANCE (fixture->acct)));
qof_instance_mark_clean (QOF_INSTANCE (fixture->acct));
qof_instance_get (QOF_INSTANCE (fixture->acct),
"lot-next-id", &next_id_r,
"online-id", &online_id_r,
"ofx-income-account", &ofx_income_acct_r,
"ab-account-id", &ab_acct_id_r,
"ab-bank-code", &ab_bank_code_r,
"ab-account-uid", &ab_acct_uid_r,
"ab-trans-retrieval", &trans_retr_r,
NULL);
g_assert_cmpint (next_id, ==, next_id_r);
g_assert_cmpstr (online_id, ==, online_id_r);
g_assert (guid_equal (ofx_income_acct, ofx_income_acct_r));
g_assert_cmpstr (ab_acct_id, ==, ab_acct_id_r);
g_assert_cmpstr (ab_bank_code, ==, ab_bank_code_r);
g_assert_cmpint (ab_acct_uid, ==, ab_acct_uid_r);
g_assert (timespec_equal (&trans_retr, trans_retr_r));
g_assert (!qof_instance_is_dirty (QOF_INSTANCE (fixture->acct)));
}
static void
test_trans_kvp_properties (Fixture *fixture, gconstpointer pData)
{
GncGUID *invoice = guid_malloc ();
GncGUID *from_sx = guid_malloc ();
GncGUID *invoice_r, *from_sx_r;
gchar *online_id = "my online id";
gchar *online_id_r;
xaccTransBeginEdit (fixture->trans);
qof_instance_set (QOF_INSTANCE (fixture->trans),
"invoice", invoice,
"from-sched-xaction", from_sx,
"online-id", online_id,
NULL);
g_assert (qof_instance_is_dirty (QOF_INSTANCE (fixture->trans)));
qof_instance_mark_clean (QOF_INSTANCE (fixture->trans));
qof_instance_get (QOF_INSTANCE (fixture->trans),
"invoice", &invoice_r,
"from-sched-xaction", &from_sx_r,
"online-id", &online_id_r,
NULL);
g_assert (guid_equal (invoice, invoice_r));
g_assert (guid_equal (from_sx, from_sx_r));
g_assert_cmpstr (online_id, ==, online_id_r);
g_assert (!qof_instance_is_dirty (QOF_INSTANCE (fixture->trans)));
guid_free (invoice);
guid_free (invoice_r);
guid_free (from_sx);
guid_free (from_sx_r);
g_free (online_id_r);
}
static void
test_split_kvp_properties (Fixture *fixture, gconstpointer pData)
{
gchar *debit_formula = "e^xdydx";
gchar *credit_formula = "seccostansin";
gchar *sx_shares = "43";
gchar *online_id = "my_online_id";
gchar *debit_formula_r, *credit_formula_r, *sx_shares_r;
gchar *online_id_r;
GncGUID *sx_account = guid_malloc ();
GncGUID *sx_account_r;
gnc_numeric debit_numeric = gnc_numeric_create (123, 456);
gnc_numeric credit_numeric = gnc_numeric_create (789, 456);
gnc_numeric *debit_numeric_r, *credit_numeric_r;
qof_begin_edit (QOF_INSTANCE (fixture->split));
qof_instance_set (QOF_INSTANCE (fixture->split),
"sx-debit-formula", debit_formula,
"sx-debit-numeric", &debit_numeric,
"sx-credit-formula", credit_formula,
"sx-credit-numeric", &credit_numeric,
"sx-account", sx_account,
"sx-shares", sx_shares,
"online-id", online_id,
NULL);
g_assert (qof_instance_is_dirty (QOF_INSTANCE (fixture->split)));
qof_instance_mark_clean (QOF_INSTANCE (fixture->split));
qof_instance_get (QOF_INSTANCE (fixture->split),
"sx-debit-formula", &debit_formula_r,
"sx-debit-numeric", &debit_numeric_r,
"sx-credit-formula", &credit_formula_r,
"sx-credit-numeric", &credit_numeric_r,
"sx-account", &sx_account_r,
"sx-shares", &sx_shares_r,
"online-id", &online_id_r,
NULL);
g_assert_cmpstr (debit_formula, ==, debit_formula_r);
g_assert (gnc_numeric_equal (debit_numeric, *debit_numeric_r));
g_assert_cmpstr (credit_formula, ==, credit_formula_r);
g_assert (gnc_numeric_equal (credit_numeric, *credit_numeric_r));
g_assert (guid_equal (sx_account, sx_account_r));
g_assert_cmpstr (sx_shares, ==, sx_shares_r);
g_assert_cmpstr (online_id, ==, online_id_r);
g_assert (!qof_instance_is_dirty (QOF_INSTANCE (fixture->split)));
g_free (debit_formula_r);
g_free (debit_numeric_r);
g_free (credit_formula_r);
g_free (credit_numeric_r);
qof_begin_edit (QOF_INSTANCE (fixture->split));
qof_instance_set (QOF_INSTANCE (fixture->split),
"sx-credit-formula", NULL,
NULL);
qof_instance_get (QOF_INSTANCE (fixture->split),
"sx-credit-formula", &credit_numeric_r,
NULL);
g_assert (credit_numeric_r == NULL);
g_free (sx_shares_r);
g_free (online_id_r);
guid_free (sx_account);
guid_free (sx_account_r);
}
static void
test_lot_kvp_properties (Fixture *fixture, gconstpointer pData)
{
GncGUID *invoice = guid_malloc ();
GncGUID *invoice_r;
gint64 owner_type = 47;
gint64 owner_type_r;
GncGUID *owner = guid_malloc ();
GncGUID *owner_r;
qof_begin_edit (QOF_INSTANCE (fixture->lot));
qof_instance_set (QOF_INSTANCE (fixture->lot),
"invoice", invoice,
"owner-type", owner_type,
"owner-guid", owner,
NULL);
g_assert (qof_instance_is_dirty (QOF_INSTANCE (fixture->lot)));
qof_instance_mark_clean (QOF_INSTANCE (fixture->lot));
qof_instance_get (QOF_INSTANCE (fixture->lot),
"invoice", &invoice_r,
"owner-type", &owner_type_r,
"owner-guid", &owner_r,
NULL);
g_assert (guid_equal (invoice, invoice_r));
g_assert_cmpint (owner_type, ==, owner_type_r);
g_assert (guid_equal (owner, owner_r));
g_assert (!qof_instance_is_dirty (QOF_INSTANCE (fixture->lot)));
guid_free (invoice);
guid_free (invoice_r);
guid_free (owner);
guid_free (owner_r);
}
static void
test_customer_kvp_properties (Fixture *fixture, gconstpointer pData)
{
gchar *pdf_dir = "/foo/bar/baz";
gchar *pdf_dir_r;
GncGUID *inv_acct = guid_malloc ();
GncGUID *pmt_acct = guid_malloc ();
GncGUID *inv_acct_r, *pmt_acct_r;
qof_begin_edit (QOF_INSTANCE (fixture->cust));
qof_instance_set (QOF_INSTANCE (fixture->cust),
"export-pdf-dir", pdf_dir,
"invoice-last-posted-account", inv_acct,
"payment-last-account", pmt_acct,
NULL);
g_assert (qof_instance_is_dirty (QOF_INSTANCE (fixture->cust)));
qof_instance_mark_clean (QOF_INSTANCE (fixture->cust));
qof_instance_get (QOF_INSTANCE (fixture->cust),
"export-pdf-dir", &pdf_dir_r,
"invoice-last-posted-account", &inv_acct_r,
"payment-last-account", &pmt_acct_r,
NULL);
g_assert_cmpstr (pdf_dir, ==, pdf_dir_r);
g_assert (guid_equal (inv_acct, inv_acct_r));
g_assert (guid_equal (pmt_acct, pmt_acct_r));
guid_free (inv_acct);
guid_free (inv_acct_r);
guid_free (pmt_acct);
guid_free (pmt_acct_r);
g_free (pdf_dir_r);
}
static void
test_employee_kvp_properties (Fixture *fixture, gconstpointer pData)
{
gchar *pdf_dir = "/foo/bar/baz";
gchar *pdf_dir_r;
GncGUID *inv_acct = guid_malloc ();
GncGUID *pmt_acct = guid_malloc ();
GncGUID *inv_acct_r, *pmt_acct_r;
qof_begin_edit (QOF_INSTANCE (fixture->emp));
qof_instance_set (QOF_INSTANCE (fixture->emp),
"export-pdf-dir", pdf_dir,
"invoice-last-posted-account", inv_acct,
"payment-last-account", pmt_acct,
NULL);
g_assert (qof_instance_is_dirty (QOF_INSTANCE (fixture->emp)));
qof_instance_mark_clean (QOF_INSTANCE (fixture->emp));
qof_instance_get (QOF_INSTANCE (fixture->emp),
"export-pdf-dir", &pdf_dir_r,
"invoice-last-posted-account", &inv_acct_r,
"payment-last-account", &pmt_acct_r,
NULL);
g_assert_cmpstr (pdf_dir, ==, pdf_dir_r);
g_assert (guid_equal (inv_acct, inv_acct_r));
g_assert (guid_equal (pmt_acct, pmt_acct_r));
guid_free (inv_acct);
guid_free (inv_acct_r);
guid_free (pmt_acct);
guid_free (pmt_acct_r);
g_free (pdf_dir_r);
}
static void
test_job_kvp_properties (Fixture *fixture, gconstpointer pData)
{
gchar *pdf_dir = "/foo/bar/baz";
gchar *pdf_dir_r;
qof_begin_edit (QOF_INSTANCE (fixture->job));
qof_instance_set (QOF_INSTANCE (fixture->job),
"export-pdf-dir", pdf_dir,
NULL);
g_assert (qof_instance_is_dirty (QOF_INSTANCE (fixture->job)));
qof_instance_mark_clean (QOF_INSTANCE (fixture->job));
qof_instance_get (QOF_INSTANCE (fixture->job),
"export-pdf-dir", &pdf_dir_r,
NULL);
g_assert_cmpstr (pdf_dir, ==, pdf_dir_r);
g_free (pdf_dir_r);
}
static void
test_vendor_kvp_properties (Fixture *fixture, gconstpointer pData)
{
gchar *pdf_dir = "/foo/bar/baz";
gchar *pdf_dir_r;
GncGUID *inv_acct = guid_malloc ();
GncGUID *pmt_acct = guid_malloc ();
GncGUID *inv_acct_r, *pmt_acct_r;
qof_begin_edit (QOF_INSTANCE (fixture->vend));
qof_instance_set (QOF_INSTANCE (fixture->vend),
"export-pdf-dir", pdf_dir,
"invoice-last-posted-account", inv_acct,
"payment-last-account", pmt_acct,
NULL);
g_assert (qof_instance_is_dirty (QOF_INSTANCE (fixture->vend)));
qof_instance_mark_clean (QOF_INSTANCE (fixture->vend));
qof_instance_get (QOF_INSTANCE (fixture->vend),
"export-pdf-dir", &pdf_dir_r,
"invoice-last-posted-account", &inv_acct_r,
"payment-last-account", &pmt_acct_r,
NULL);
g_assert_cmpstr (pdf_dir, ==, pdf_dir_r);
g_assert (guid_equal (inv_acct, inv_acct_r));
g_assert (guid_equal (pmt_acct, pmt_acct_r));
guid_free (inv_acct);
guid_free (inv_acct_r);
guid_free (pmt_acct);
guid_free (pmt_acct_r);
g_free (pdf_dir_r);
}
void test_suite_engine_kvp_properties (void)
{
GNC_TEST_ADD (suitename, "Account", Fixture, NULL, setup_account, test_account_kvp_properties, teardown);
GNC_TEST_ADD (suitename, "Transaction", Fixture, NULL, setup_trans, test_trans_kvp_properties, teardown);
GNC_TEST_ADD (suitename, "Split", Fixture, NULL, setup_split, test_split_kvp_properties, teardown);
GNC_TEST_ADD (suitename, "Lot", Fixture, NULL, setup_lot, test_lot_kvp_properties, teardown);
GNC_TEST_ADD (suitename, "Customer", Fixture, NULL, setup_customer, test_customer_kvp_properties, teardown);
GNC_TEST_ADD (suitename, "Employee", Fixture, NULL, setup_employee, test_employee_kvp_properties, teardown);
GNC_TEST_ADD (suitename, "Job", Fixture, NULL, setup_job, test_job_kvp_properties, teardown);
GNC_TEST_ADD (suitename, "Vendor", Fixture, NULL, setup_vendor, test_vendor_kvp_properties, teardown);
}

View File

@ -31,6 +31,7 @@ extern void test_suite_budget();
extern void test_suite_gncInvoice();
extern void test_suite_transaction();
extern void test_suite_split();
extern void test_suite_engine_kvp_properties (void);
int
main (int argc,
@ -49,6 +50,7 @@ main (int argc,
test_suite_gncInvoice();
test_suite_transaction();
test_suite_split();
test_suite_engine_kvp_properties ();
return g_test_run( );
}

View File

@ -24,9 +24,11 @@
*
*********************************************************************/
#include "config.h"
#include <config.h>
#include <glib.h>
#include "qof.h"
#include <qof.h>
#include <qofinstance-p.h>
#include "gncJobP.h"
#include "gncInvoiceP.h"
#include "gncCustomerP.h"

View File

@ -24,8 +24,10 @@
*
*********************************************************************/
#include "config.h"
#include <config.h>
#include <glib.h>
#include <qofinstance-p.h>
#include "gncInvoiceP.h"
#include "gncCustomerP.h"
#include "gncJobP.h"

View File

@ -25,6 +25,7 @@
#include <unittest-support.h>
#include <gnc-event.h>
#include <gnc-gdate-utils.h>
#include <qofinstance-p.h>
/* Add specific headers for this class */
#include "../Account.h"
#include "../AccountP.h"
@ -444,11 +445,11 @@ test_gnc_account_name_violations_errmsg ()
message = gnc_account_name_violations_errmsg (separator, nonames);
g_assert (message == NULL);
validation_message = g_strdup_printf (
"The separator character \"%s\" is used in one or more account "
"names.\n\nThis will result in unexpected behaviour. "
"Either change the account names or choose another separator "
"character.\n\nBelow you will find the list of invalid account names:\n"
"%s", separator, account_list);
"The separator character \"%s\" is used in one or more account "
"names.\n\nThis will result in unexpected behaviour. "
"Either change the account names or choose another separator "
"character.\n\nBelow you will find the list of invalid account names:\n"
"%s", separator, account_list);
message = gnc_account_name_violations_errmsg (separator, badnames);
g_assert_cmpstr ( message, == , validation_message);
g_free (validation_message);
@ -1356,6 +1357,8 @@ test_xaccAccountOrder ( )
g_assert (xaccAccountOrder (ab, aa) == 1);
ab = xaccMallocAccount (book);
qof_instance_increase_editlevel (aa);
qof_instance_increase_editlevel (ab);
g_object_set (G_OBJECT (aa),
"code", "3333",
"type", ACCT_TYPE_ASSET,
@ -1398,6 +1401,8 @@ test_xaccAccountOrder ( )
"name", "bar",
NULL);
g_assert_cmpint (xaccAccountOrder (aa, ab), < , 0);
qof_instance_decrease_editlevel (aa);
qof_instance_decrease_editlevel (ab);
xaccAccountBeginEdit (aa);
xaccAccountDestroy (aa);
@ -2157,7 +2162,9 @@ test_xaccAccountType_Stuff (void)
g_assert_cmpstr (typestr_uc, == , typename);
g_free (typestr_uc);
qof_instance_increase_editlevel (acc);
g_object_set (acc, "type", type, NULL);
qof_instance_decrease_editlevel (acc);
if (type == ACCT_TYPE_STOCK || type == ACCT_TYPE_MUTUAL ||
type == ACCT_TYPE_CURRENCY)
g_assert (xaccAccountIsPriced (acc));
@ -2401,11 +2408,13 @@ test_gnc_account_merge_children (Fixture *fixture, gconstpointer pData)
*/
sig4 = test_signal_new (QOF_INSTANCE (div), QOF_EVENT_MODIFY, NULL);
sig5 = test_signal_new (QOF_INSTANCE (div1), QOF_EVENT_MODIFY, NULL);
qof_instance_increase_editlevel (div1);
g_object_set (div1, "name", "div", NULL);
qof_instance_decrease_editlevel (div1);
gnc_account_merge_children (taxable);
g_assert_cmpint (gnc_account_n_descendants (taxable), == , taxable_desc - 1);
test_signal_assert_hits (sig4, 1);
test_signal_assert_hits (sig5, 4);
test_signal_assert_hits (sig5, 3);
test_signal_free (sig4);
test_signal_free (sig5);
gnc_account_merge_children (expense);

View File

@ -38,7 +38,7 @@ extern "C"
#include <TransactionP.h>
#include <gnc-lot.h>
#include <gnc-event.h>
#include <qofbookslots.h>
#include <qofinstance-p.h>
#ifdef HAVE_GLIB_2_38
#define _Q "'"
@ -318,15 +318,15 @@ test_xaccDupeSplit (Fixture *fixture, gconstpointer pData)
g_assert (split->gains_split != f_split->gains_split);
}
/* xaccSplitClone
/* xaccSplitCloneNoKvp
Split *
xaccSplitClone (const Split *s)// C: 1
xaccSplitCloneNoKvp (const Split *s)// C: 1
*/
static void
test_xaccSplitClone (Fixture *fixture, gconstpointer pData)
test_xaccSplitCloneNoKvp (Fixture *fixture, gconstpointer pData)
{
Split *f_split = fixture->split;
Split *split = xaccSplitClone (f_split);
Split *split = xaccSplitCloneNoKvp (f_split);
g_assert (split != fixture->split);
g_assert (qof_instance_get_guid (split) != qof_instance_get_guid (f_split));
@ -339,7 +339,7 @@ test_xaccSplitClone (Fixture *fixture, gconstpointer pData)
g_assert (split->lot == f_split->lot);
g_assert_cmpstr (split->memo, ==, f_split->memo);
g_assert_cmpstr (split->action, ==, f_split->action);
g_assert (kvp_frame_compare (split->inst.kvp_data, f_split->inst.kvp_data) == 0);
g_assert (kvp_frame_is_empty (split->inst.kvp_data));
g_assert_cmpint (split->reconciled, ==, f_split->reconciled);
g_assert (timespec_equal (&(split->date_reconciled), &(f_split->date_reconciled)));
g_assert (gnc_numeric_equal (split->value, f_split->value));
@ -417,7 +417,7 @@ xaccSplitEqual(const Split *sa, const Split *sb,// C: 2 in 2 SCM: 1
static void
test_xaccSplitEqual (Fixture *fixture, gconstpointer pData)
{
Split *split1 = xaccSplitClone (fixture->split);
Split *split1 = xaccSplitCloneNoKvp (fixture->split);
Split *split2 = xaccDupeSplit (fixture->split);
gchar *msg01 = "[xaccSplitEqual] one is NULL";
gchar *msg02 = "[xaccSplitEqual] GUIDs differ";
@ -468,9 +468,11 @@ test_xaccSplitEqual (Fixture *fixture, gconstpointer pData)
split1->parent = fixture->split->parent;
g_assert (xaccSplitEqual (fixture->split, split1, FALSE, TRUE, TRUE) == TRUE);
/* Now set the GUIDs equal and see that the comparison passes */
qof_instance_increase_editlevel (split1->parent);
g_object_set (G_OBJECT (split1),
"guid", qof_instance_get_guid (QOF_INSTANCE(fixture->split)),
NULL);
qof_instance_increase_editlevel (split1->parent);
g_assert (xaccSplitEqual (fixture->split, split1, TRUE, TRUE, TRUE) == TRUE);
g_assert_cmpint (checkA.hits, ==, 3);
g_assert_cmpint (checkB.hits, ==, 1);
@ -607,10 +609,12 @@ test_xaccSplitCommitEdit (Fixture *fixture, gconstpointer pData)
g_assert_cmpint (checkB.hits, ==, 2);
qof_instance_mark_clean (QOF_INSTANCE (fixture->split->parent));
qof_instance_increase_editlevel (fixture->split->acc);
g_object_set (fixture->split->acc,
"sort-dirty", FALSE,
"balance-dirty", FALSE,
NULL);
qof_instance_decrease_editlevel (fixture->split->acc);
qof_instance_set_dirty (QOF_INSTANCE (fixture->split));
xaccSplitCommitEdit (fixture->split);
@ -780,16 +784,6 @@ test_get_commodity_denom (Fixture *fixture, gconstpointer pData)
fixture->split->acc = acc;
g_assert_cmpint (fixture->func->get_commodity_denom (fixture->split), ==, denom);
}
/* xaccSplitGetSlots
KvpFrame *
xaccSplitGetSlots (const Split * s)// C: 17 in 8
Simple passthrough, no test.
*/
// Not Used
/* xaccSplitSetSlots_nc
void
xaccSplitSetSlots_nc(Split *s, KvpFrame *frm)//
*/
/* xaccSplitSetSharePriceAndAmount
void
xaccSplitSetSharePriceAndAmount (Split *s, gnc_numeric price, gnc_numeric amt)// C: 1
@ -1115,8 +1109,9 @@ test_xaccSplitOrder (Fixture *fixture, gconstpointer pData)
{
const char *slot_path;
Split *split = fixture->split;
Split *o_split = xaccMallocSplit (xaccSplitGetBook (split));
Transaction *o_txn = xaccMallocTransaction (xaccSplitGetBook (split));
QofBook *book = xaccSplitGetBook (split);
Split *o_split = xaccMallocSplit (book);
Transaction *o_txn = xaccMallocTransaction (book);
Transaction *txn = split->parent;
g_assert_cmpint (xaccSplitOrder (split, split), ==, 0);
@ -1155,11 +1150,12 @@ test_xaccSplitOrder (Fixture *fixture, gconstpointer pData)
*/
/* create correct slot path */
slot_path = (const char *) g_strconcat( KVP_OPTION_PATH, "/",
OPTION_SECTION_ACCOUNTS, "/", OPTION_NAME_NUM_FIELD_SOURCE, NULL );
g_assert( slot_path != NULL );
g_test_message( "Testing with use-split-action-for-num set to true - t" );
qof_book_set_string_option( xaccSplitGetBook (split), slot_path, "t" );
qof_book_begin_edit (book);
qof_instance_set (QOF_INSTANCE (book),
"split-action-num-field", "t",
NULL);
qof_book_commit_edit (book);
g_assert(qof_book_use_split_action_for_num_field(xaccSplitGetBook(split)) == TRUE);
g_assert_cmpint (xaccSplitOrder (split, o_split), ==, -1);
@ -1171,7 +1167,11 @@ test_xaccSplitOrder (Fixture *fixture, gconstpointer pData)
o_split->action = NULL;
split->action = "foo";
o_split->parent = NULL;
qof_book_set_string_option( xaccSplitGetBook (split), slot_path, "f" );
qof_book_begin_edit (book);
qof_instance_set (QOF_INSTANCE (book),
"split-action-num-field", "f",
NULL);
qof_book_commit_edit (book);
g_assert(qof_book_use_split_action_for_num_field(xaccSplitGetBook(split)) == FALSE);
split->parent = NULL;
/* This should return > 0 because o_split has no memo string */
@ -1772,7 +1772,6 @@ test_xaccSplitGetOtherSplit (Fixture *fixture, gconstpointer pData)
Split *split2 = xaccMallocSplit (book);
Account *acc2 = xaccMallocAccount (book);
KvpValue *kvptrue = kvp_value_new_string ("t");
KvpFrame *book_slots = qof_book_get_slots (book);
g_assert (xaccSplitGetOtherSplit (NULL) == NULL);
g_assert (xaccSplitGetOtherSplit (split1) == NULL);
@ -1801,9 +1800,11 @@ test_xaccSplitGetOtherSplit (Fixture *fixture, gconstpointer pData)
g_assert (kvp_frame_get_slot (split->inst.kvp_data, "lot-split") == NULL);
kvp_frame_set_slot (split1->inst.kvp_data, "lot-split", NULL);
g_assert (kvp_frame_get_slot (split1->inst.kvp_data, "lot-split") == NULL);
kvp_frame_set_slot_path (book_slots, kvptrue, KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_TRADING_ACCOUNTS, NULL);
qof_book_begin_edit (book);
qof_instance_set (QOF_INSTANCE (book),
"trading-accts", "t",
NULL);
qof_book_commit_edit (book);
g_assert (xaccTransUseTradingAccounts (txn));
g_assert (xaccSplitGetOtherSplit (split) == NULL);
split2->acc = acc2;
@ -1882,7 +1883,7 @@ test_suite_split (void)
GNC_TEST_ADD_FUNC (suitename, "gnc split set & get property", test_gnc_split_set_get_property);
GNC_TEST_ADD (suitename, "xaccMallocSplit", Fixture, NULL, setup, test_xaccMallocSplit, teardown);
GNC_TEST_ADD (suitename, "xaccDupeSplit", Fixture, NULL, setup, test_xaccDupeSplit, teardown);
GNC_TEST_ADD (suitename, "xaccSplitClone", Fixture, NULL, setup, test_xaccSplitClone, teardown);
GNC_TEST_ADD (suitename, "xaccSplitCloneNoKvp", Fixture, NULL, setup, test_xaccSplitCloneNoKvp, teardown);
GNC_TEST_ADD (suitename, "mark split", Fixture, NULL, setup, test_mark_split, teardown);
GNC_TEST_ADD (suitename, "xaccSplitEqualCheckBal", Fixture, NULL, setup, test_xaccSplitEqualCheckBal, teardown);
GNC_TEST_ADD (suitename, "xaccSplitEqual", Fixture, NULL, setup, test_xaccSplitEqual, teardown);

View File

@ -1,5 +1,5 @@
/********************************************************************
* utest-Transaction.c: GLib g_test test suite for Transaction.c. *
* utest-Transaction.c: GLib g_test test suite for Transaction.c. *
* Copyright 2012 John Ralls <jralls@ceridwen.us> *
* *
* This program is free software; you can redistribute it and/or *
@ -33,7 +33,6 @@
#include "../gnc-lot.h"
#include "../gnc-event.h"
#include <qof.h>
#include <qofbookslots.h>
#include <qofbackend-p.h>
#ifdef HAVE_GLIB_2_38
@ -569,12 +568,12 @@ test_xaccTransSortSplits (Fixture *fixture, gconstpointer pData)
xaccTransCommitEdit (txn);
}
/* xaccDupeTransaction
Transaction *
xaccDupeTransaction (const Transaction *from)// Local: 1:0:0
/* dupe_trans
static Transaction *
dupe_trans (const Transaction *from)// Local: 1:0:0
*/
static void
test_xaccDupeTransaction (Fixture *fixture, gconstpointer pData)
test_dupe_trans (Fixture *fixture, gconstpointer pData)
{
Timespec posted = gnc_dmy2timespec (12, 7, 2011);
Timespec entered = gnc_dmy2timespec (14, 7, 2011);
@ -587,7 +586,7 @@ test_xaccDupeTransaction (Fixture *fixture, gconstpointer pData)
kvp_frame_set_string (old->inst.kvp_data, "/foo/bar/baz",
"The Great Waldo Pepper");
new = xaccDupeTransaction (old);
new = fixture->func->dupe_trans (old);
g_assert_cmpstr (new->num, ==, old->num);
g_assert_cmpstr (new->description, ==, old->description);
@ -1048,14 +1047,14 @@ test_xaccTransGetImbalance_trading (Fixture *fixture,
Account *acc1 = xaccMallocAccount (book);
Account *acc2 = xaccMallocAccount (book);
gnc_numeric value;
gchar *trading_account_path = g_strdup_printf("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_TRADING_ACCOUNTS);
MonetaryList *mlist;
qof_book_begin_edit (book);
qof_instance_set (QOF_INSTANCE (book),
"trading-accts", "t",
NULL);
qof_book_commit_edit (book);
qof_book_set_string_option( book, trading_account_path, "t" );
g_free (trading_account_path);
/* Without trading splits, the list is unbalanced */
/* Without trading splits, the list is unbalanced */
mlist = xaccTransGetImbalance (fixture->txn);
g_assert_cmpint (g_list_length (mlist), ==, 2);
gnc_monetary_list_free (mlist);
@ -1135,12 +1134,13 @@ test_xaccTransIsBalanced_trading (Fixture *fixture, gconstpointer pData)
Split *split2 = xaccMallocSplit (book);
Account *acc1 = xaccMallocAccount (book);
Account *acc2 = xaccMallocAccount (book);
gchar *trading_account_path = g_strdup_printf("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_TRADING_ACCOUNTS);
qof_book_set_string_option( book, trading_account_path, "t" );
g_free (trading_account_path);
qof_book_begin_edit (book);
qof_instance_set (QOF_INSTANCE (book),
"trading-accts", "t",
NULL);
qof_book_commit_edit (book);
xaccAccountSetCommodity (acc1, fixture->curr);
xaccAccountSetCommodity (acc2, fixture->comm);
xaccAccountSetType (acc1, ACCT_TYPE_TRADING);
@ -1398,29 +1398,27 @@ void
xaccTransDestroy (Transaction *trans)// C: 26 in 15 SCM: 4 in 4 Local: 3:0:0
*/
static void
test_xaccTransDestroy ()
test_xaccTransDestroy (Fixture *fixture, gconstpointer pData)
{
QofBook *book = qof_book_new ();
Transaction *txn = xaccMallocTransaction (book);
Transaction *dupe = xaccDupeTransaction (txn);
Transaction *txn = fixture->txn;
QofBook *book = qof_instance_get_book (QOF_INSTANCE (txn));
Transaction *dupe = xaccTransClone (txn);
xaccTransBeginEdit (txn);
g_assert (!qof_instance_get_destroying (QOF_INSTANCE (txn)));
g_assert (xaccTransEqual (txn, dupe, FALSE, TRUE, TRUE, TRUE));
g_assert (xaccTransEqual (txn, dupe, FALSE, TRUE, FALSE, TRUE));
xaccTransDestroy (txn);
g_assert (qof_instance_get_destroying (QOF_INSTANCE (txn)));
g_assert (xaccTransEqual (txn, dupe, FALSE, TRUE, TRUE, TRUE));
g_assert (xaccTransEqual (txn, dupe, FALSE, TRUE, FALSE, TRUE));
xaccTransRollbackEdit (txn);
qof_book_mark_readonly (book);
xaccTransBeginEdit (txn);
xaccTransDestroy (txn);
g_assert (qof_instance_get_destroying (QOF_INSTANCE (txn)));
g_assert (xaccTransEqual (txn, dupe, FALSE, TRUE, TRUE, TRUE));
g_assert (xaccTransEqual (txn, dupe, FALSE, TRUE, FALSE, TRUE));
xaccTransRollbackEdit (txn);
test_destroy (txn);
test_destroy (dupe);
test_destroy (book);
}
/* destroy_gains
static void
@ -1645,10 +1643,6 @@ test_xaccTransCommitEdit (void)
xaccTransSetCurrency (txn, curr);
xaccSplitSetParent (split1, txn);
xaccSplitSetParent (split2, txn);
/* xaccTransCommitEdit doesn't do anything with kvp
kvp_frame_set_double (frame, "/qux/quux/corge", 123.456);
qof_instance_set_slots (QOF_INSTANCE (txn), frame);
*/
}
/* Setup's done, now test: */
xaccTransCommitEdit (txn);
@ -1790,7 +1784,7 @@ static void
test_xaccTransOrder_num_action (Fixture *fixture, gconstpointer pData)
{
Transaction *txnA = fixture->txn;
Transaction *txnB = xaccDupeTransaction (txnA);
Transaction *txnB = fixture->func->dupe_trans (txnA);
g_assert_cmpint (xaccTransOrder_num_action (txnA, NULL, NULL, NULL), ==, -1);
g_assert_cmpint (xaccTransOrder_num_action (NULL, NULL, txnA, NULL), ==, 1);
@ -2042,7 +2036,7 @@ test_suite_transaction (void)
GNC_TEST_ADD (suitename, "gnc transaction set/get property", Fixture, NULL, setup, test_gnc_transaction_set_get_property, teardown);
GNC_TEST_ADD (suitename, "xaccMallocTransaction", Fixture, NULL, setup, test_xaccMallocTransaction, teardown);
GNC_TEST_ADD (suitename, "xaccTransSortSplits", Fixture, NULL, setup, test_xaccTransSortSplits, teardown);
GNC_TEST_ADD (suitename, "xaccDupeTransaction", Fixture, NULL, setup, test_xaccDupeTransaction, teardown);
GNC_TEST_ADD (suitename, "dupe_trans", Fixture, NULL, setup, test_dupe_trans, teardown);
GNC_TEST_ADD (suitename, "xaccTransClone", Fixture, NULL, setup, test_xaccTransClone, teardown);
GNC_TEST_ADD (suitename, "xaccTransCopyFromClipBoard", Fixture, NULL, setup, test_xaccTransCopyFromClipBoard, teardown);
GNC_TEST_ADD (suitename, "xaccTransCopyFromClipBoard No-Start", Fixture, NULL, setup, test_xaccTransCopyFromClipBoard_no_start, teardown);
@ -2063,7 +2057,7 @@ test_suite_transaction (void)
GNC_TEST_ADD (suitename, "xaccTransSetCurrency", Fixture, NULL, setup, test_xaccTransSetCurrency, teardown);
GNC_TEST_ADD_FUNC (suitename, "xaccTransBeginEdit", test_xaccTransBeginEdit);
GNC_TEST_ADD_FUNC (suitename, "xaccTransDestroy", test_xaccTransDestroy);
GNC_TEST_ADD (suitename, "xaccTransDestroy", Fixture, NULL, setup, test_xaccTransDestroy, teardown);
GNC_TEST_ADD (suitename, "destroy gains", GainsFixture, NULL, setup_with_gains, test_destroy_gains, teardown_with_gains);
GNC_TEST_ADD (suitename, "do destroy", GainsFixture, NULL, setup_with_gains, test_do_destroy, teardown_with_gains);
GNC_TEST_ADD (suitename, "was trans emptied", Fixture, NULL, setup, test_was_trans_emptied, teardown);

View File

@ -1054,7 +1054,7 @@ gnc_preferences_dialog_create(void)
GtkWidget *dialog, *notebook, *label, *image;
GtkWidget *box, *date, *period, *currency;
GHashTable *prefs_table;
GDate* gdate;
GDate* gdate = NULL;
gchar buf[128];
GtkListStore *store;
GtkTreePath *path;
@ -1120,16 +1120,10 @@ gnc_preferences_dialog_create(void)
book = gnc_get_current_book();
book_frame = qof_book_get_slots(book);
month = kvp_frame_get_gint64(book_frame, "/book/fyear_end/month");
day = kvp_frame_get_gint64(book_frame, "/book/fyear_end/day");
date_is_valid = g_date_valid_dmy(day, month, 2005 /* not leap year */);
if (date_is_valid)
{
g_date_clear(&fy_end, 1);
g_date_set_dmy(&fy_end, day, month, G_DATE_BAD_YEAR);
}
g_date_clear (&fy_end, 1);
qof_instance_get (QOF_INSTANCE (book),
"fy-end", &fy_end,
NULL);
box = GTK_WIDGET(gtk_builder_get_object (builder,
"pref/" GNC_PREFS_GROUP_ACCT_SUMMARY "/" GNC_PREF_START_PERIOD));
period = gnc_period_select_new(TRUE);

View File

@ -3973,20 +3973,21 @@ gnc_book_options_dialog_apply_cb(GNCOptionWin * optionwin,
gpointer user_data)
{
GNCOptionDB * options = user_data;
kvp_frame *slots = qof_book_get_slots (gnc_get_current_book ());
gboolean use_split_action_for_num_before =
qof_book_use_split_action_for_num_field (gnc_get_current_book ());
gboolean use_split_action_for_num_after;
QofBook *book = gnc_get_current_book ();
if (!options) return;
gnc_option_db_commit (options);
gnc_option_db_save_to_kvp (options, slots, TRUE);
qof_book_kvp_changed (gnc_get_current_book());
qof_book_begin_edit (book);
qof_book_save_options (book, gnc_option_db_save_to_kvp, options, TRUE);
use_split_action_for_num_after =
qof_book_use_split_action_for_num_field (gnc_get_current_book ());
if (use_split_action_for_num_before != use_split_action_for_num_after)
gnc_book_option_num_field_source_change_cb (use_split_action_for_num_after);
qof_book_commit_edit (book);
}
static void
@ -4002,12 +4003,12 @@ gnc_book_options_dialog_close_cb(GNCOptionWin * optionwin,
GtkWidget *
gnc_book_options_dialog_cb (gboolean modal, gchar *title)
{
kvp_frame *slots = qof_book_get_slots (gnc_get_current_book ());
QofBook *book = gnc_get_current_book ();
GNCOptionDB *options;
GNCOptionWin *optionwin;
options = gnc_option_db_new_for_type (QOF_ID_BOOK);
gnc_option_db_load_from_kvp (options, slots);
qof_book_load_options (book, gnc_option_db_load_from_kvp, options);
gnc_option_db_clean (options);
optionwin = gnc_options_dialog_new_modal (modal,

View File

@ -397,30 +397,20 @@ const char *
gnc_tree_util_split_reg_template_get_transfer_entry (Split *split)
{
static char *name = NULL;
Account *account;
GncGUID *guid = NULL;
kvp_frame *kvpf;
/* Callers either g_strdup the return or use it as a temp for comparison,
so we keep our static ref and free it on every call. */
g_free (name);
if (!split)
return NULL;
kvpf = xaccSplitGetSlots (split);
g_free (name);
if (kvpf)
{
Account *account;
GncGUID *guid;
guid = kvp_value_get_guid(
kvp_frame_get_slot_path (kvpf, "sched-xaction", "account", NULL));
account = xaccAccountLookup (guid, gnc_get_current_book ());
name = account ? gnc_get_account_name_for_register (account) : NULL;
}
else
name = NULL;
qof_instance_get (QOF_INSTANCE (split),
"sx-account", &guid,
NULL);
account = xaccAccountLookup (guid, gnc_get_current_book ());
name = account ? gnc_get_account_name_for_register (account) : NULL;
return name;
}
@ -429,20 +419,27 @@ gnc_tree_util_split_reg_template_get_transfer_entry (Split *split)
const char *
gnc_tree_util_split_reg_template_get_fdebt_entry (Split *split)
{
kvp_frame *kvpf = xaccSplitGetSlots (split);
gchar *formula = NULL;
return kvp_value_get_string(
kvp_frame_get_slot_path (kvpf, "sched-xaction", "debit-formula", NULL));
g_return_val_if_fail (split != NULL, NULL);
qof_instance_get (QOF_INSTANCE (split),
"sx-debit-formula", &formula,
NULL);
return formula;
}
const char *
gnc_tree_util_split_reg_template_get_fcred_entry (Split *split)
{
kvp_frame *kvpf = xaccSplitGetSlots (split);
gchar *formula = NULL;
return kvp_value_get_string(
kvp_frame_get_slot_path (kvpf, "sched-xaction", "credit-formula", NULL));
g_return_val_if_fail (split != NULL, NULL);
qof_instance_get (QOF_INSTANCE (split),
"sx-credit-formula", &formula,
NULL);
return formula;
}

View File

@ -1730,43 +1730,44 @@ gtva_currency_changed_cb (void)
gtva_update_column_names (ptr->data);
}
}
/* This function implements a custom mapping between an account's KVP
* and the cell renderer's 'text' property. */
/* Retrieve a specified account string property and put the result
* into the tree column's text property.
*/
static void
account_cell_kvp_data_func (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *s_model,
GtkTreeIter *s_iter,
gpointer key)
account_cell_property_data_func (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *s_model,
GtkTreeIter *s_iter,
gpointer key)
{
Account *account;
kvp_frame * frame;
gchar *string = NULL;
g_return_if_fail (GTK_IS_TREE_MODEL_SORT (s_model));
account = gnc_tree_view_account_get_account_from_iter(s_model, s_iter);
frame = xaccAccountGetSlots(account);
g_object_set (G_OBJECT (cell),
"text", kvp_frame_get_string(frame, (gchar *)key),
"xalign", 0.0,
NULL);
qof_instance_get (QOF_INSTANCE (account),
key, &string,
NULL);
if (string == NULL)
string = "";
g_object_set (G_OBJECT (cell), "text", string, "xalign", 0.0, NULL);
}
GtkTreeViewColumn *
gnc_tree_view_account_add_kvp_column (GncTreeViewAccount *view,
gnc_tree_view_account_add_property_column (GncTreeViewAccount *view,
const gchar *column_title,
const gchar *kvp_key)
const gchar *propname)
{
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view), NULL);
g_return_val_if_fail (kvp_key != NULL, NULL);
g_return_val_if_fail (propname != NULL, NULL);
column = gnc_tree_view_add_text_column(GNC_TREE_VIEW(view), column_title,
kvp_key, NULL, "Sample text",
propname, NULL, "Sample text",
-1, -1, NULL);
/* This new kvp column has only had one renderer added to it so
@ -1775,8 +1776,8 @@ gnc_tree_view_account_add_kvp_column (GncTreeViewAccount *view,
g_object_set (G_OBJECT (renderer), "xalign", 1.0, NULL);
gtk_tree_view_column_set_cell_data_func (column, renderer,
account_cell_kvp_data_func,
g_strdup(kvp_key), g_free);
account_cell_property_data_func,
g_strdup(propname), g_free);
return column;
}

View File

@ -203,20 +203,19 @@ void gnc_tree_view_account_notes_edited_cb(Account *account, GtkTreeViewColumn *
/** Add a new column to the set of columns in an account tree view.
* This column will be visible as soon as it is added and will
* display the contents of the specified KVP slot.
* display the contents of the specified account property
*
* @param view A pointer to an account tree view.
*
* @param column_title The title for this new column.
*
* @param kvp_key The lookup key to use for looking up data in the
* account KVP structures. The value associated with this key is what
* will be displayed in the column.
* @param propname The g_object_property name of the desired
* value. This must be a string property.
*/
GtkTreeViewColumn *
gnc_tree_view_account_add_kvp_column (GncTreeViewAccount *view,
const gchar *column_title,
const gchar *kvp_key);
gnc_tree_view_account_add_property_column (GncTreeViewAccount *view,
const gchar *column_title,
const gchar *propname);
/** @} */

View File

@ -4801,9 +4801,8 @@ gtv_sr_edited_template_cb (GtkCellRendererText *cell, const gchar *path_string,
if (viewcol == COL_TRANSFERVOID)
{
Account *template_acc;
Account *acct;
const GncGUID *acctGUID;
kvp_frame *kvpf;
Account *acct;
/* save the account GncGUID into the kvp_data. */
view->priv->stop_cell_move = FALSE;
@ -4822,9 +4821,9 @@ gtv_sr_edited_template_cb (GtkCellRendererText *cell, const gchar *path_string,
}
acctGUID = xaccAccountGetGUID (acct);
kvpf = xaccSplitGetSlots (split);
kvp_frame_set_slot_path (kvpf, kvp_value_new_guid (acctGUID),
GNC_SX_ID, GNC_SX_ACCOUNT, NULL);
qof_instance_set (QOF_INSTANCE (split),
"sx-account", acctGUID,
NULL);
template_acc = gnc_tree_model_split_reg_get_template_account (model);
@ -4844,20 +4843,11 @@ gtv_sr_edited_template_cb (GtkCellRendererText *cell, const gchar *path_string,
/* Setup the debit and credit fields */
if (viewcol == COL_DEBIT)
{
kvp_frame *kvpf;
char *error_loc;
gnc_numeric new_value;
gboolean parse_result;
kvpf = xaccSplitGetSlots (split);
DEBUG ("kvp_frame debit before: %s\n", kvp_frame_to_string (kvpf));
/* Setup the debit formula */
kvp_frame_set_slot_path (kvpf, kvp_value_new_string (new_text),
GNC_SX_ID,
GNC_SX_DEBIT_FORMULA,
NULL);
/* If the value can be parsed into a numeric result, store that
* numeric value additionally. See above comment.*/
@ -4866,45 +4856,22 @@ gtv_sr_edited_template_cb (GtkCellRendererText *cell, const gchar *path_string,
{
new_value = gnc_numeric_zero();
}
kvp_frame_set_slot_path (kvpf, kvp_value_new_numeric (new_value),
GNC_SX_ID,
GNC_SX_DEBIT_NUMERIC,
NULL);
DEBUG ("kvp_frame debit after: %s\n", kvp_frame_to_string (kvpf));
/* Blank the credit formula */
kvp_frame_set_slot_path (kvpf, kvp_value_new_string (NULL),
GNC_SX_ID,
GNC_SX_CREDIT_FORMULA,
NULL);
new_value = gnc_numeric_zero();
kvp_frame_set_slot_path (kvpf, kvp_value_new_numeric (new_value),
GNC_SX_ID,
GNC_SX_CREDIT_NUMERIC,
NULL);
qof_instance_set (QOF_INSTANCE (split),
"sx-debit-formula", new_text,
"sx-debit-numeric", &new_value,
"sx-credit-formula", NULL,
"sx-credit-numeric", NULL,
NULL);
}
/* Setup the debit and credit fields */
if (viewcol == COL_CREDIT)
{
kvp_frame *kvpf;
char *error_loc;
gnc_numeric new_value;
gboolean parse_result;
kvpf = xaccSplitGetSlots (split);
DEBUG ("kvp_frame credit before: %s\n", kvp_frame_to_string (kvpf));
/* Setup the credit formula */
kvp_frame_set_slot_path (kvpf, kvp_value_new_string (new_text),
GNC_SX_ID,
GNC_SX_CREDIT_FORMULA,
NULL);
/* If the value can be parsed into a numeric result (without any
/* If the value can be parsed into a numeric result (without any
* further variable definitions), store that numeric value
* additionally in the kvp. Otherwise store a zero numeric
* there.*/
@ -4913,24 +4880,12 @@ gtv_sr_edited_template_cb (GtkCellRendererText *cell, const gchar *path_string,
{
new_value = gnc_numeric_zero();
}
kvp_frame_set_slot_path (kvpf, kvp_value_new_numeric (new_value),
GNC_SX_ID,
GNC_SX_CREDIT_NUMERIC,
NULL);
DEBUG ("kvp_frame credit after: %s\n", kvp_frame_to_string (kvpf));
/* Blank the debit formula */
kvp_frame_set_slot_path (kvpf, kvp_value_new_string (NULL),
GNC_SX_ID,
GNC_SX_DEBIT_FORMULA,
NULL);
new_value = gnc_numeric_zero();
kvp_frame_set_slot_path (kvpf, kvp_value_new_numeric (new_value),
GNC_SX_ID,
GNC_SX_DEBIT_NUMERIC,
NULL);
qof_instance_set (QOF_INSTANCE (split),
"sx-credit-formula", new_text,
"sx-credit-numeric", &new_value,
"sx-debit-formula", NULL,
"sx-debit-numeric", NULL,
NULL);
}
/* set the amount to an innocuous value */
xaccSplitSetValue (split, gnc_numeric_create (0, 1));

View File

@ -1008,18 +1008,17 @@ finish_book_options_helper(GNCOptionWin * optionwin,
gpointer user_data)
{
GNCOptionDB * options = user_data;
kvp_frame *slots = qof_book_get_slots (gnc_get_current_book ());
QofBook *book = gnc_get_current_book ();
gboolean use_split_action_for_num_before =
qof_book_use_split_action_for_num_field (gnc_get_current_book ());
qof_book_use_split_action_for_num_field (book);
gboolean use_split_action_for_num_after;
if (!options) return;
gnc_option_db_commit (options);
gnc_option_db_save_to_kvp (options, slots, TRUE);
qof_book_kvp_changed (gnc_get_current_book());
qof_book_save_options (book, gnc_option_db_save_to_kvp, options, TRUE);
use_split_action_for_num_after =
qof_book_use_split_action_for_num_field (gnc_get_current_book ());
qof_book_use_split_action_for_num_field (book);
if (use_split_action_for_num_before != use_split_action_for_num_after)
gnc_book_option_num_field_source_change_cb (use_split_action_for_num_after);
}
@ -1119,11 +1118,11 @@ book_options_dialog_close_cb(GNCOptionWin * optionwin,
static void
assistant_instert_book_options_page (hierarchy_data *data)
{
kvp_frame *slots = qof_book_get_slots (gnc_get_current_book ());
GtkWidget *vbox = gtk_vbox_new (FALSE, 0);
data->options = gnc_option_db_new_for_type (QOF_ID_BOOK);
gnc_option_db_load_from_kvp (data->options, slots);
qof_book_load_options (gnc_get_current_book (),
gnc_option_db_load_from_kvp, data->options);
gnc_option_db_clean (data->options);
data->optionwin = gnc_options_dialog_new_modal (TRUE, _("New Book Options"));

View File

@ -549,9 +549,7 @@ gnc_sxed_check_consistent( GncSxEditorDialog *sxed )
int numIters, i;
GHashTable *vars, *txns;
GList *splitList = NULL;
char *str;
kvp_frame *f;
kvp_value *v;
gchar *credit_formula = NULL, *debit_formula = NULL;
Split *s;
Transaction *t;
gnc_numeric tmp;
@ -559,8 +557,10 @@ gnc_sxed_check_consistent( GncSxEditorDialog *sxed )
gpointer unusedKey, unusedValue;
unbalanceable = FALSE; /* innocent until proven guilty */
vars = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)gnc_sx_variable_free);
txns = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
vars = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
(GDestroyNotify)gnc_sx_variable_free);
txns = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
g_free);
numIters = NUM_ITERS_NO_VARS;
/**
* Plan:
@ -604,10 +604,10 @@ gnc_sxed_check_consistent( GncSxEditorDialog *sxed )
for ( ; splitList; splitList = splitList->next )
{
GncGUID *acct_guid;
Account *acct;
gnc_commodity *split_cmdty;
txnCreditDebitSums *tcds;
GncGUID *acct_guid = NULL;
Account *acct = NULL;
gnc_commodity *split_cmdty = NULL;
txnCreditDebitSums *tcds = NULL;
s = (Split*)splitList->data;
t = xaccSplitGetParent( s );
@ -622,14 +622,11 @@ gnc_sxed_check_consistent( GncSxEditorDialog *sxed )
g_hash_table_insert( txns, (gpointer)t, (gpointer)tcds );
}
f = xaccSplitGetSlots( s );
/* contains the guid of the split's actual account. */
v = kvp_frame_get_slot_path(f,
GNC_SX_ID,
GNC_SX_ACCOUNT,
NULL);
acct_guid = kvp_value_get_guid( v );
qof_instance_get (QOF_INSTANCE (s),
"sx-account", &acct_guid,
"sx-credit-formula", &credit_formula,
"sx-debit-formula", &debit_formula,
NULL);
acct = xaccAccountLookup( acct_guid, gnc_get_current_book ());
split_cmdty = xaccAccountGetCommodity(acct);
if (base_cmdty == NULL)
@ -638,62 +635,48 @@ gnc_sxed_check_consistent( GncSxEditorDialog *sxed )
}
multi_commodity |= !gnc_commodity_equal(split_cmdty, base_cmdty);
v = kvp_frame_get_slot_path( f,
GNC_SX_ID,
GNC_SX_CREDIT_FORMULA,
NULL );
if ( v
&& (str = kvp_value_get_string(v))
&& strlen( str ) != 0 )
{
if ( gnc_sx_parse_vars_from_formula( str, vars, &tmp ) < 0 )
{
GString *errStr;
if ( g_strcmp0 (credit_formula, "") != 0 &&
gnc_sx_parse_vars_from_formula(credit_formula, vars,
&tmp ) < 0 )
{
GString *errStr;
errStr = g_string_sized_new( 32 );
g_string_printf( errStr,
_( "Couldn't parse credit formula for "
"split \"%s\"." ),
xaccSplitGetMemo( s ) );
gnc_error_dialog( GTK_WIDGET(sxed->dialog), "%s",
errStr->str );
g_string_free( errStr, TRUE );
errStr = g_string_sized_new( 32 );
g_string_printf( errStr,
_( "Couldn't parse credit formula for "
"split \"%s\"." ),
xaccSplitGetMemo( s ) );
gnc_error_dialog( GTK_WIDGET(sxed->dialog), "%s",
errStr->str );
g_string_free( errStr, TRUE );
return FALSE;
}
tcds->creditSum =
gnc_numeric_add( tcds->creditSum, tmp, 100,
(GNC_DENOM_AUTO | GNC_HOW_DENOM_LCD) );
tmp = gnc_numeric_zero();
}
v = kvp_frame_get_slot_path( f,
GNC_SX_ID,
GNC_SX_DEBIT_FORMULA,
NULL );
if ( v
&& (str = kvp_value_get_string(v))
&& strlen(str) != 0 )
{
if ( gnc_sx_parse_vars_from_formula( str, vars, &tmp ) < 0 )
{
GString *errStr;
return FALSE;
}
tcds->creditSum =
gnc_numeric_add( tcds->creditSum, tmp, 100,
(GNC_DENOM_AUTO | GNC_HOW_DENOM_LCD) );
tmp = gnc_numeric_zero();
if ( g_strcmp0 (debit_formula, "") != 0 &&
gnc_sx_parse_vars_from_formula( debit_formula, vars,
&tmp ) < 0 )
{
GString *errStr;
errStr = g_string_sized_new( 32 );
g_string_printf( errStr,
_( "Couldn't parse debit formula for "
"split \"%s\"." ),
xaccSplitGetMemo( s ) );
gnc_error_dialog( GTK_WIDGET(sxed->dialog), "%s",
(gchar*)errStr->str );
g_string_free( errStr, TRUE );
errStr = g_string_sized_new( 32 );
g_string_printf( errStr,
_( "Couldn't parse debit formula for "
"split \"%s\"." ),
xaccSplitGetMemo( s ) );
gnc_error_dialog( GTK_WIDGET(sxed->dialog), "%s",
(gchar*)errStr->str );
g_string_free( errStr, TRUE );
return FALSE;
}
tcds->debitSum = gnc_numeric_add( tcds->debitSum, tmp, 100,
(GNC_DENOM_AUTO | GNC_HOW_DENOM_LCD) );
tmp = gnc_numeric_zero();
}
}
return FALSE;
}
tcds->debitSum = gnc_numeric_add( tcds->debitSum, tmp, 100,
(GNC_DENOM_AUTO | GNC_HOW_DENOM_LCD) );
tmp = gnc_numeric_zero();
}
g_hash_table_foreach( txns,
check_credit_debit_balance,

View File

@ -546,9 +546,7 @@ gnc_sxed_check_consistent (GncSxEditorDialog2 *sxed)
int numIters, i;
GHashTable *vars, *txns;
GList *splitList = NULL;
char *str;
kvp_frame *f;
kvp_value *v;
char *credit_formula = NULL, *debit_formula = NULL;
Split *s;
Transaction *t;
gnc_numeric tmp;
@ -597,7 +595,7 @@ gnc_sxed_check_consistent (GncSxEditorDialog2 *sxed)
for (; splitList; splitList = splitList->next)
{
GncGUID *acct_guid;
GncGUID *acct_guid = NULL;
Account *acct;
gnc_commodity *split_cmdty;
txnCreditDebitSums *tcds;
@ -615,77 +613,60 @@ gnc_sxed_check_consistent (GncSxEditorDialog2 *sxed)
g_hash_table_insert (txns, (gpointer)t, (gpointer)tcds);
}
f = xaccSplitGetSlots (s);
/* contains the guid of the split's actual account. */
v = kvp_frame_get_slot_path (f,
GNC_SX_ID,
GNC_SX_ACCOUNT,
NULL);
acct_guid = kvp_value_get_guid (v);
acct = xaccAccountLookup (acct_guid, gnc_get_current_book ());
split_cmdty = xaccAccountGetCommodity (acct);
qof_instance_get (QOF_INSTANCE (s),
"sx-account", &acct_guid,
"sx-credit-formula", &credit_formula,
"sx-debit-formula", &debit_formula,
NULL);
acct = xaccAccountLookup( acct_guid, gnc_get_current_book ());
split_cmdty = xaccAccountGetCommodity(acct);
if (base_cmdty == NULL)
{
base_cmdty = split_cmdty;
}
multi_commodity |= !gnc_commodity_equal (split_cmdty, base_cmdty);
multi_commodity |= !gnc_commodity_equal(split_cmdty, base_cmdty);
v = kvp_frame_get_slot_path (f,
GNC_SX_ID,
GNC_SX_CREDIT_FORMULA,
NULL);
if (v
&& (str = kvp_value_get_string (v))
&& strlen( str ) != 0)
{
if (gnc_sx_parse_vars_from_formula (str, vars, &tmp ) < 0)
{
GString *errStr;
if ( g_strcmp0 (credit_formula, "") != 0 &&
gnc_sx_parse_vars_from_formula(credit_formula, vars,
&tmp ) < 0 )
{
GString *errStr;
errStr = g_string_sized_new (32);
g_string_printf (errStr,
_( "Couldn't parse credit formula for "
"split \"%s\"."),
xaccSplitGetMemo (s));
gnc_error_dialog (GTK_WIDGET (sxed->dialog), "%s",
errStr->str);
g_string_free (errStr, TRUE);
errStr = g_string_sized_new( 32 );
g_string_printf( errStr,
_( "Couldn't parse credit formula for "
"split \"%s\"." ),
xaccSplitGetMemo( s ) );
gnc_error_dialog( GTK_WIDGET(sxed->dialog), "%s",
errStr->str );
g_string_free( errStr, TRUE );
return FALSE;
}
tcds->creditSum =
gnc_numeric_add (tcds->creditSum, tmp, 100,
(GNC_DENOM_AUTO | GNC_HOW_DENOM_LCD));
tmp = gnc_numeric_zero();
}
v = kvp_frame_get_slot_path (f,
GNC_SX_ID,
GNC_SX_DEBIT_FORMULA,
NULL);
if (v
&& (str = kvp_value_get_string (v))
&& strlen(str) != 0 )
{
if (gnc_sx_parse_vars_from_formula (str, vars, &tmp ) < 0)
{
GString *errStr;
return FALSE;
}
tcds->creditSum =
gnc_numeric_add( tcds->creditSum, tmp, 100,
(GNC_DENOM_AUTO | GNC_HOW_DENOM_LCD) );
tmp = gnc_numeric_zero();
if ( g_strcmp0 (debit_formula, "") != 0 &&
gnc_sx_parse_vars_from_formula( debit_formula, vars,
&tmp ) < 0 )
{
GString *errStr;
errStr = g_string_sized_new (32);
g_string_printf (errStr,
_( "Couldn't parse debit formula for "
"split \"%s\"."),
xaccSplitGetMemo (s));
gnc_error_dialog (GTK_WIDGET (sxed->dialog), "%s",
(gchar*)errStr->str);
g_string_free (errStr, TRUE);
errStr = g_string_sized_new( 32 );
g_string_printf( errStr,
_( "Couldn't parse debit formula for "
"split \"%s\"." ),
xaccSplitGetMemo( s ) );
gnc_error_dialog( GTK_WIDGET(sxed->dialog), "%s",
(gchar*)errStr->str );
g_string_free( errStr, TRUE );
return FALSE;
}
tcds->debitSum = gnc_numeric_add (tcds->debitSum, tmp, 100,
(GNC_DENOM_AUTO | GNC_HOW_DENOM_LCD));
tmp = gnc_numeric_zero();
}
return FALSE;
}
tcds->debitSum = gnc_numeric_add( tcds->debitSum, tmp, 100,
(GNC_DENOM_AUTO | GNC_HOW_DENOM_LCD) );
tmp = gnc_numeric_zero();
}
g_hash_table_foreach (txns,

View File

@ -3646,39 +3646,30 @@ gnc_plugin_page_register2_cmd_schedule (GtkAction *action,
/* If the transaction has a sched-xact KVP frame, then go to the editor
* for the existing SX; otherwise, do the sx-from-trans dialog. */
{
kvp_frame *txn_frame;
kvp_value *kvp_val;
/* set a kvp-frame element in the transaction indicating and
* pointing-to the SX this was created from. */
txn_frame = xaccTransGetSlots (trans);
if ( txn_frame != NULL )
{
kvp_val = kvp_frame_get_slot (txn_frame, "from-sched-xaction");
if (kvp_val)
{
GncGUID *fromSXId = kvp_value_get_guid (kvp_val);
SchedXaction *theSX = NULL;
GList *sxElts;
GncGUID *fromSXId = NULL;
SchedXaction *theSX = NULL;
GList *sxElts;
qof_instance_get (QOF_INSTANCE (trans),
"from-sched-xaction", &fromSXId,
NULL);
/* Get the correct SX */
for ( sxElts = gnc_book_get_schedxactions (gnc_get_current_book())->sx_list;
(!theSX) && sxElts;
sxElts = sxElts->next )
{
SchedXaction *sx = (SchedXaction*)sxElts->data;
theSX =
((guid_equal (xaccSchedXactionGetGUID (sx), fromSXId))
? sx : NULL);
}
/* Get the correct SX */
for ( sxElts = gnc_book_get_schedxactions (gnc_get_current_book())->sx_list;
(!theSX) && sxElts;
sxElts = sxElts->next )
{
SchedXaction *sx = (SchedXaction*)sxElts->data;
theSX =
((guid_equal (xaccSchedXactionGetGUID (sx), fromSXId))
? sx : NULL);
}
if (theSX)
{
gnc_ui_scheduled_xaction_editor_dialog_create2 (theSX, FALSE);
LEAVE(" ");
return;
}
}
}
if (theSX)
{
gnc_ui_scheduled_xaction_editor_dialog_create2 (theSX, FALSE);
LEAVE(" ");
return;
}
}
gnc_sx_create_from_trans (trans);
LEAVE(" ");

View File

@ -1387,38 +1387,29 @@ gsr_default_schedule_handler( GNCSplitReg *gsr, gpointer data )
/* If the transaction has a sched-xact KVP frame, then go to the editor
* for the existing SX; otherwise, do the sx-from-trans dialog. */
{
kvp_frame *txn_frame;
kvp_value *kvp_val;
/* set a kvp-frame element in the transaction indicating and
* pointing-to the SX this was created from. */
txn_frame = xaccTransGetSlots( pending_trans );
if ( txn_frame != NULL )
{
kvp_val = kvp_frame_get_slot( txn_frame, "from-sched-xaction" );
if ( kvp_val )
{
GncGUID *fromSXId = kvp_value_get_guid( kvp_val );
SchedXaction *theSX = NULL;
GList *sxElts;
GncGUID *fromSXId = NULL;
SchedXaction *theSX = NULL;
GList *sxElts;
qof_instance_get (QOF_INSTANCE (pending_trans),
"from-sched-xaction", &fromSXId,
NULL);
/* Get the correct SX */
for ( sxElts = gnc_book_get_schedxactions(gnc_get_current_book())->sx_list;
(!theSX) && sxElts;
sxElts = sxElts->next )
{
SchedXaction *sx = (SchedXaction*)sxElts->data;
theSX =
( ( guid_equal( xaccSchedXactionGetGUID( sx ), fromSXId ) )
? sx : NULL );
}
/* Get the correct SX */
for ( sxElts = gnc_book_get_schedxactions (gnc_get_current_book())->sx_list;
(!theSX) && sxElts;
sxElts = sxElts->next )
{
SchedXaction *sx = (SchedXaction*)sxElts->data;
theSX =
((guid_equal (xaccSchedXactionGetGUID (sx), fromSXId))
? sx : NULL);
}
if ( theSX )
{
gnc_ui_scheduled_xaction_editor_dialog_create(theSX, FALSE);
return;
}
}
}
if ( theSX )
{
gnc_ui_scheduled_xaction_editor_dialog_create(theSX, FALSE);
return;
}
}
gnc_sx_create_from_trans(pending_trans);

View File

@ -18,13 +18,11 @@ libgncmod_generic_import_la_SOURCES = \
import-parse.c \
import-utilities.c \
import-settings.c \
import-match-map.c \
import-main-matcher.c \
gncmod-generic-import.c
gncincludedir = ${GNC_INCLUDE_DIR}
gncinclude_HEADERS = \
import-match-map.h \
import-parse.h
noinst_HEADERS = \
@ -32,7 +30,6 @@ noinst_HEADERS = \
import-backend.h \
import-commodity-matcher.h \
import-main-matcher.h \
import-match-map.h \
import-match-picker.h \
import-settings.h \
import-utilities.h

View File

@ -32,134 +32,105 @@
#include "gnc-ab-kvp.h"
#define AB_KEY "hbci"
#define AB_ACCOUNT_ID "account-id"
#define AB_ACCOUNT_UID "account-uid"
#define AB_BANK_CODE "bank-code"
#define AB_TRANS_RETRIEVAL "trans-retrieval"
#define AB_TEMPLATES "template-list"
/* This static indicates the debugging module that this .o belongs to. */
G_GNUC_UNUSED static QofLogModule log_module = G_LOG_DOMAIN;
static kvp_frame *gnc_ab_get_account_kvp(const Account *a, gboolean create);
static kvp_frame *gnc_ab_get_book_kvp(QofBook *b, gboolean create);
const gchar *
gnc_ab_get_account_accountid(const Account *a)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, FALSE);
kvp_value *value = kvp_frame_get_slot(frame, AB_ACCOUNT_ID);
return kvp_value_get_string(value);
gchar *id = NULL;
qof_instance_get (QOF_INSTANCE (a),
"ab-account-id", &id,
NULL);
return id;
}
void
gnc_ab_set_account_accountid(Account *a, const gchar *id)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, TRUE);
kvp_value *value = kvp_value_new_string(id);
xaccAccountBeginEdit(a);
kvp_frame_set_slot_nc(frame, AB_ACCOUNT_ID, value);
qof_instance_set_dirty(QOF_INSTANCE (a));
qof_instance_set (QOF_INSTANCE (a),
"ab-account-id", id,
NULL);
xaccAccountCommitEdit(a);
}
const gchar *
gnc_ab_get_account_bankcode(const Account *a)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, FALSE);
kvp_value *value = kvp_frame_get_slot(frame, AB_BANK_CODE);
return kvp_value_get_string(value);
gchar *code = NULL;
qof_instance_get (QOF_INSTANCE (a),
"ab-bank-code", &code,
NULL);
return code;
}
void
gnc_ab_set_account_bankcode(Account *a, const gchar *code)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, TRUE);
kvp_value *value = kvp_value_new_string(code);
xaccAccountBeginEdit(a);
kvp_frame_set_slot_nc(frame, AB_BANK_CODE, value);
qof_instance_set_dirty(QOF_INSTANCE (a));
qof_instance_set (QOF_INSTANCE (a),
"ab-bank-code", code,
NULL);
xaccAccountCommitEdit(a);
}
guint32
gnc_ab_get_account_uid(const Account *a)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, FALSE);
kvp_value *value = kvp_frame_get_slot(frame, AB_ACCOUNT_UID);
return (guint32) kvp_value_get_gint64(value);
guint64 uid = 0LL;
qof_instance_get (QOF_INSTANCE (a),
"ab-account-uid", &uid,
NULL);
return (guint32)uid;
}
void
gnc_ab_set_account_uid(Account *a, guint32 uid)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, TRUE);
kvp_value *value = kvp_value_new_gint64(uid);
xaccAccountBeginEdit(a);
kvp_frame_set_slot_nc(frame, AB_ACCOUNT_UID, value);
qof_instance_set_dirty(QOF_INSTANCE (a));
qof_instance_set (QOF_INSTANCE (a),
"ab-account-uid", (guint64)uid,
NULL);
xaccAccountCommitEdit(a);
}
Timespec
gnc_ab_get_account_trans_retrieval(const Account *a)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, FALSE);
kvp_value *value = kvp_frame_get_slot(frame, AB_TRANS_RETRIEVAL);
return kvp_value_get_timespec(value);
Timespec t = {0LL, 0LL};
qof_instance_get (QOF_INSTANCE (a),
"ab-trans-retrieval", &t,
NULL);
return t;
}
void
gnc_ab_set_account_trans_retrieval(Account *a, Timespec time)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, TRUE);
kvp_value *value = kvp_value_new_timespec(time);
xaccAccountBeginEdit(a);
kvp_frame_set_slot_nc(frame, AB_TRANS_RETRIEVAL, value);
qof_instance_set_dirty(QOF_INSTANCE (a));
qof_instance_set (QOF_INSTANCE (a),
"ab-trans-retrieval", &time,
NULL);
xaccAccountCommitEdit(a);
}
GList *
gnc_ab_get_book_template_list(QofBook *b)
{
kvp_frame *frame = gnc_ab_get_book_kvp(b, FALSE);
kvp_value *value = kvp_frame_get_slot(frame, AB_TEMPLATES);
return kvp_value_get_glist(value);
GList *template_list = NULL;
qof_instance_get (QOF_INSTANCE (b),
"ab-templates", &template_list,
NULL);
return template_list;
}
void
gnc_ab_set_book_template_list(QofBook *b, GList *template_list)
{
kvp_frame *frame = gnc_ab_get_book_kvp(b, TRUE);
kvp_value *value = kvp_value_new_glist_nc(template_list);
kvp_frame_set_slot_nc(frame, AB_TEMPLATES, value);
qof_book_kvp_changed (b);
}
static kvp_frame *
gnc_ab_get_account_kvp(const Account *a, gboolean create)
{
kvp_frame *toplevel = xaccAccountGetSlots(a);
kvp_frame *result = kvp_frame_get_frame(toplevel, AB_KEY);
if (!result && create)
{
result = kvp_frame_new();
kvp_frame_add_frame_nc(toplevel, AB_KEY, result);
}
return result;
}
static kvp_frame *
gnc_ab_get_book_kvp(QofBook *b, gboolean create)
{
kvp_frame *toplevel = qof_book_get_slots(b);
kvp_frame *result = kvp_frame_get_frame(toplevel, AB_KEY);
if (!result && create)
{
result = kvp_frame_new();
kvp_frame_add_frame_nc(toplevel, AB_KEY, result);
}
return result;
qof_instance_set (QOF_INSTANCE (b),
"ab-templates", &template_list,
NULL);
}

View File

@ -114,8 +114,8 @@ build_acct_tree(AccountPickerDialog *picker)
g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
/* Add our custom column. */
col = gnc_tree_view_account_add_kvp_column (picker->account_tree,
_("Account ID"), "online_id");
col = gnc_tree_view_account_add_property_column (picker->account_tree,
_("Account ID"), "online-id");
g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
gtk_container_add(GTK_CONTAINER(picker->account_tree_sw),

View File

@ -44,6 +44,40 @@
#include "gnc-prefs.h"
#include "gnc-ui-util.h"
/* Private interface to Account GncImportMatchMap functions */
/** @{
Obtain an ImportMatchMap object from an Account */
extern GncImportMatchMap * gnc_account_create_imap (Account *acc);
/*@}*/
/* Look up an Account in the map */
extern Account* gnc_imap_find_account(GncImportMatchMap *imap,
const char* category,
const char *key);
/* Store an Account in the map. This mapping is immediatly stored in
the underlying kvp frame, regardless of whether the MatchMap is
destroyed later or not. */
extern void gnc_imap_add_account (GncImportMatchMap *imap,
const char *category,
const char *key, Account *acc);
/* Look up an Account in the map from a GList* of pointers to strings(tokens)
from the current transaction */
extern Account* gnc_imap_find_account_bayes (GncImportMatchMap *imap,
GList* tokens);
/* Store an Account in the map. This mapping is immediatly stored in
the underlying kvp frame, regardless of whether the MatchMap is
destroyed later or not. */
extern void gnc_imap_add_account_bayes (GncImportMatchMap *imap,
GList* tokens,
Account *acc);
#define GNCIMPORT_DESC "desc"
#define GNCIMPORT_MEMO "memo"
#define GNCIMPORT_PAYEE "payee"
/********************************************************************\
* Constants *
@ -457,6 +491,15 @@ TransactionGetTokens(GNCImportTransInfo *info)
/* return the pointer to the GList */
return tokens;
}
/* Destroy an import map. But all stored entries will still continue
* to exist in the underlying kvp frame of the account.
*/
static void
gnc_imap_destroy (GncImportMatchMap *imap)
{
if (!imap) return;
g_free (imap);
}
/* searches using the GNCImportTransInfo through all existing transactions
* if there is an exact match of the description and memo
@ -471,7 +514,7 @@ matchmap_find_destination (GncImportMatchMap *matchmap, GNCImportTransInfo *info
g_assert (info);
tmp_map = ((matchmap != NULL) ? matchmap :
gnc_imap_create_from_account
gnc_account_create_imap
(xaccSplitGetAccount
(gnc_import_TransInfo_get_fsplit (info))));
@ -541,7 +584,7 @@ matchmap_store_destination (GncImportMatchMap *matchmap,
tmp_matchmap = ((matchmap != NULL) ?
matchmap :
gnc_imap_create_from_account
gnc_account_create_imap
(xaccSplitGetAccount
(gnc_import_TransInfo_get_fsplit (trans_info))));

View File

@ -29,11 +29,11 @@
#define TRANSACTION_MATCHER_H
#include "Transaction.h"
#include "import-match-map.h"
#include "import-settings.h"
typedef struct _transactioninfo GNCImportTransInfo;
typedef struct _matchinfo GNCImportMatchInfo;
typedef struct _GncImportMatchMap GncImportMatchMap;
typedef enum _action
{

View File

@ -44,7 +44,6 @@
#include "gnc-ui-util.h"
#include "gnc-engine.h"
#include "import-settings.h"
#include "import-match-map.h"
#include "import-match-picker.h"
#include "import-backend.h"
#include "import-account-matcher.h"

View File

@ -1,545 +0,0 @@
/********************************************************************\
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
* Boston, MA 02110-1301, USA gnu@gnu.org *
\********************************************************************/
/** @addtogroup Import_Export
@{ */
/** @internal
@file import-match-map.c
@brief Generic import mapper service, maps strings->accounts
*
An import mapper service that stores Account Maps for the
generic importer. This allows importers to map various
"strings" to Gnucash accounts in a generic manner.
@author Copyright (C) 2002,2003 Derek Atkins <derek@ihtfp.com>
*/
#include "config.h"
#include <string.h>
#include <glib.h>
#include "import-match-map.h"
#include "gnc-ui-util.h"
#include "gnc-engine.h"
/********************************************************************\
* Constants *
\********************************************************************/
static QofLogModule log_module = GNC_MOD_IMPORT;
struct _GncImportMatchMap
{
kvp_frame * frame;
Account * acc;
QofBook * book;
};
#define IMAP_FRAME "import-map"
#define IMAP_FRAME_BAYES "import-map-bayes"
static GncImportMatchMap *
gnc_imap_create_from_frame (kvp_frame *frame, Account *acc, QofBook *book)
{
GncImportMatchMap *imap;
g_return_val_if_fail (frame != NULL, NULL);
g_return_val_if_fail ((acc && !book) || (!acc && book), NULL);
imap = g_new0(GncImportMatchMap, 1);
imap->frame = frame;
/* Cache the book for easy lookups; store the account/book for
* marking dirtiness
*/
if (acc)
book = gnc_account_get_book (acc);
imap->acc = acc;
imap->book = book;
return imap;
}
/** Obtain an ImportMatchMap object from an Account or a Book */
GncImportMatchMap * gnc_imap_create_from_account (Account *acc)
{
kvp_frame * frame;
if (!acc) return NULL;
frame = xaccAccountGetSlots (acc);
g_return_val_if_fail (frame != NULL, NULL);
return gnc_imap_create_from_frame (frame, acc, NULL);
}
GncImportMatchMap * gnc_imap_create_from_book (QofBook *book)
{
kvp_frame * frame;
if (!book) return NULL;
frame = qof_book_get_slots (book);
g_return_val_if_fail (frame != NULL, NULL);
return gnc_imap_create_from_frame (frame, NULL, book);
}
/** Destroy an import map */
void gnc_imap_destroy (GncImportMatchMap *imap)
{
if (!imap) return;
g_free (imap);
}
/** Clear an import map -- this removes ALL entries in the map */
void gnc_imap_clear (GncImportMatchMap *imap)
{
if (!imap) return;
xaccAccountBeginEdit (imap->acc);
/* Clear the IMAP_FRAME kvp */
kvp_frame_set_slot_path (imap->frame, NULL, IMAP_FRAME);
/* Clear the bayes kvp, IMAP_FRAME_BAYES */
kvp_frame_set_slot_path (imap->frame, NULL, IMAP_FRAME_BAYES);
qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
xaccAccountCommitEdit (imap->acc);
}
/** Look up an Account in the map */
Account * gnc_imap_find_account (GncImportMatchMap *imap, const char *category,
const char *key)
{
kvp_value *value;
GncGUID * guid;
if (!imap || !key) return NULL;
if (!category)
{
category = key;
key = NULL;
}
value = kvp_frame_get_slot_path (imap->frame, IMAP_FRAME, category, key, NULL);
if (!value) return NULL;
guid = kvp_value_get_guid (value);
return xaccAccountLookup (guid, imap->book);
}
/** Store an Account in the map */
void gnc_imap_add_account (GncImportMatchMap *imap, const char *category,
const char *key, Account *acc)
{
kvp_value *value;
if (!imap || !key || !acc || (strlen (key) == 0)) return;
if (!category)
{
category = key;
key = NULL;
}
g_return_if_fail (acc != NULL);
value = kvp_value_new_guid (xaccAccountGetGUID (acc));
g_return_if_fail (value != NULL);
xaccAccountBeginEdit (imap->acc);
kvp_frame_set_slot_path (imap->frame, value, IMAP_FRAME, category, key, NULL);
qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
xaccAccountCommitEdit (imap->acc);
kvp_value_delete (value);
/* XXX Mark the account (or book) as dirty! */
}
/*--------------------------------------------------------------------------
Below here is the bayes transaction to account matching system
--------------------------------------------------------------------------*/
struct account_token_count
{
char* account_name;
gint64 token_count; /**< occurances of a given token for this account_name */
};
/** total_count and the token_count for a given account let us calculate the
* probability of a given account with any single token
*/
struct token_accounts_info
{
GList *accounts; /**< array of struct account_token_count */
gint64 total_count;
};
/** gpointer is a pointer to a struct token_accounts_info
* \note Can always assume that keys are unique, reduces code in this function
*/
static void buildTokenInfo(const char *key, kvp_value *value, gpointer data)
{
struct token_accounts_info *tokenInfo = (struct token_accounts_info*)data;
struct account_token_count* this_account;
// PINFO("buildTokenInfo: account '%s', token_count: '%ld'\n", (char*)key,
// (long)kvp_value_get_gint64(value));
/* add the count to the total_count */
tokenInfo->total_count += kvp_value_get_gint64(value);
/* allocate a new structure for this account and it's token count */
this_account = (struct account_token_count*)
g_new0(struct account_token_count, 1);
/* fill in the account name and number of tokens found for this account name */
this_account->account_name = (char*)key;
this_account->token_count = kvp_value_get_gint64(value);
/* append onto the glist a pointer to the new account_token_count structure */
tokenInfo->accounts = g_list_prepend(tokenInfo->accounts, this_account);
}
/** intermediate values used to calculate the bayes probability of a given account
where p(AB) = (a*b)/[a*b + (1-a)(1-b)], product is (a*b),
product_difference is (1-a) * (1-b)
*/
struct account_probability
{
double product; /* product of probabilities */
double product_difference; /* product of (1-probabilities) */
};
/** convert a hash table of account names and (struct account_probability*)
into a hash table of 100000x the percentage match value, ie. 10% would be
0.10 * 100000 = 10000
*/
#define PROBABILITY_FACTOR 100000
static void buildProbabilities(gpointer key, gpointer value, gpointer data)
{
GHashTable *final_probabilities = (GHashTable*)data;
struct account_probability *account_p = (struct account_probability*)value;
/* P(AB) = A*B / [A*B + (1-A)*(1-B)]
* NOTE: so we only keep track of a running product(A*B*C...)
* and product difference ((1-A)(1-B)...)
*/
gint32 probability =
(account_p->product /
(account_p->product + account_p->product_difference))
* PROBABILITY_FACTOR;
PINFO("P('%s') = '%d'\n", (char*)key, probability);
g_hash_table_insert(final_probabilities, key, GINT_TO_POINTER(probability));
}
/** Frees an array of the same time that buildProperties built */
static void freeProbabilities(gpointer key, gpointer value, gpointer data)
{
/* free up the struct account_probability that was allocated
* in gnc_imap_find_account_bayes()
*/
g_free(value);
}
/** holds an account name and its corresponding integer probability
the integer probability is some factor of 10
*/
struct account_info
{
char* account_name;
gint32 probability;
};
/** Find the highest probability and the corresponding account name
store in data, a (struct account_info*)
NOTE: this is a g_hash_table_foreach() function for a hash table of entries
key is a pointer to the account name, value is a gint32, 100000x
the probability for this account
*/
static void highestProbability(gpointer key, gpointer value, gpointer data)
{
struct account_info *account_i = (struct account_info*)data;
/* if the current probability is greater than the stored, store the current */
if (GPOINTER_TO_INT(value) > account_i->probability)
{
/* Save the new highest probability and the assoaciated account name */
account_i->probability = GPOINTER_TO_INT(value);
account_i->account_name = key;
}
}
#define threshold (.90 * PROBABILITY_FACTOR) /* 90% */
/** Look up an Account in the map */
Account* gnc_imap_find_account_bayes(GncImportMatchMap *imap, GList *tokens)
{
struct token_accounts_info tokenInfo; /**< holds the accounts and total
* token count for a single token */
GList *current_token; /**< pointer to the current token from the
* input GList *tokens */
GList *current_account_token; /**< pointer to the struct
* account_token_count */
struct account_token_count *account_c; /**< an account name and the number
* of times a token has appeared
* for the account */
struct account_probability *account_p; /**< intermediate storage of values
* to compute the bayes probability
* of an account */
GHashTable *running_probabilities = g_hash_table_new(g_str_hash, g_str_equal);
GHashTable *final_probabilities = g_hash_table_new(g_str_hash, g_str_equal);
struct account_info account_i;
kvp_value* value;
kvp_frame* token_frame;
ENTER(" ");
/* check to see if the imap is NULL */
if (!imap)
{
PINFO("imap is null, returning null");
LEAVE(" ");
return NULL;
}
/* find the probability for each account that contains any of the tokens
* in the input tokens list
*/
for (current_token = tokens; current_token; current_token = current_token->next)
{
/* zero out the token_accounts_info structure */
memset(&tokenInfo, 0, sizeof(struct token_accounts_info));
PINFO("token: '%s'", (char*)current_token->data);
/* find the slot for the given token off of the source account
* for these tokens, search off of the IMAP_FRAME_BAYES path so
* we aren't looking from the parent of the entire kvp tree
*/
value = kvp_frame_get_slot_path(imap->frame, IMAP_FRAME_BAYES,
(char*)current_token->data, NULL);
/* if value is null we should skip over this token */
if (!value)
continue;
/* convert the slot(value) into a the frame that contains the
* list of accounts
*/
token_frame = kvp_value_get_frame(value);
/* token_frame should NEVER be null */
if (!token_frame)
{
PERR("token '%s' has no accounts", (char*)current_token->data);
continue; /* skip over this token */
}
/* process the accounts for this token, adding the account if it
* doesn't already exist or adding to the existing accounts token
* count if it does
*/
kvp_frame_for_each_slot(token_frame, buildTokenInfo, &tokenInfo);
/* for each account we have just found, see if the account already exists
* in the list of account probabilities, if not add it
*/
for (current_account_token = tokenInfo.accounts; current_account_token;
current_account_token = current_account_token->next)
{
/* get the account name and corresponding token count */
account_c = (struct account_token_count*)current_account_token->data;
PINFO("account_c->account_name('%s'), "
"account_c->token_count('%ld')/total_count('%ld')",
account_c->account_name, (long)account_c->token_count,
(long)tokenInfo.total_count);
account_p = g_hash_table_lookup(running_probabilities,
account_c->account_name);
/* if the account exists in the list then continue
* the running probablities
*/
if (account_p)
{
account_p->product =
((double)account_c->token_count / (double)tokenInfo.total_count)
* account_p->product;
account_p->product_difference =
((double)1 - ((double)account_c->token_count /
(double)tokenInfo.total_count))
* account_p->product_difference;
PINFO("product == %f, product_difference == %f",
account_p->product, account_p->product_difference);
}
else
{
/* add a new entry */
PINFO("adding a new entry for this account");
account_p = (struct account_probability*)
g_new0(struct account_probability, 1);
/* set the product and product difference values */
account_p->product = ((double)account_c->token_count /
(double)tokenInfo.total_count);
account_p->product_difference =
(double)1 - ((double)account_c->token_count /
(double)tokenInfo.total_count);
PINFO("product == %f, product_difference == %f",
account_p->product, account_p->product_difference);
/* add the account name and (struct account_probability*)
* to the hash table */
g_hash_table_insert(running_probabilities,
account_c->account_name, account_p);
}
} /* for all accounts in tokenInfo */
/* free the data in tokenInfo */
for (current_account_token = tokenInfo.accounts; current_account_token;
current_account_token = current_account_token->next)
{
/* free up each struct account_token_count we allocated */
g_free((struct account_token_count*)current_account_token->data);
}
g_list_free(tokenInfo.accounts); /* free the accounts GList */
}
/* build a hash table of account names and their final probabilities
* from each entry in the running_probabilties hash table
*/
g_hash_table_foreach(running_probabilities, buildProbabilities,
final_probabilities);
/* find the highest probabilty and the corresponding account */
memset(&account_i, 0, sizeof(struct account_info));
g_hash_table_foreach(final_probabilities, highestProbability, &account_i);
/* free each element of the running_probabilities hash */
g_hash_table_foreach(running_probabilities, freeProbabilities, NULL);
/* free the hash tables */
g_hash_table_destroy(running_probabilities);
g_hash_table_destroy(final_probabilities);
PINFO("highest P('%s') = '%d'",
account_i.account_name ? account_i.account_name : "(null)",
account_i.probability);
/* has this probability met our threshold? */
if (account_i.probability >= threshold)
{
PINFO("found match");
LEAVE(" ");
return gnc_account_lookup_by_full_name(gnc_book_get_root_account(imap->book),
account_i.account_name);
}
PINFO("no match");
LEAVE(" ");
return NULL; /* we didn't meet our threshold, return NULL for an account */
}
/** Updates the imap for a given account using a list of tokens */
void gnc_imap_add_account_bayes(GncImportMatchMap *imap, GList *tokens, Account *acc)
{
GList *current_token;
kvp_value *value;
gint64 token_count;
char* account_fullname;
kvp_value *new_value; /* the value that will be added back into the kvp tree */
ENTER(" ");
/* if imap is null return */
if (!imap)
{
LEAVE(" ");
return;
}
g_return_if_fail (acc != NULL);
account_fullname = gnc_account_get_full_name(acc);
xaccAccountBeginEdit (imap->acc);
PINFO("account name: '%s'\n", account_fullname);
/* process each token in the list */
for (current_token = g_list_first(tokens); current_token;
current_token = current_token->next)
{
/* Jump to next iteration if the pointer is not valid or if the
string is empty. In HBCI import we almost always get an empty
string, which doesn't work in the kvp loopkup later. So we
skip this case here. */
if (!current_token->data || (*((char*)current_token->data) == '\0'))
continue;
/* start off with no tokens for this account */
token_count = 0;
PINFO("adding token '%s'\n", (char*)current_token->data);
/* is this token/account_name already in the kvp tree? */
value = kvp_frame_get_slot_path(imap->frame, IMAP_FRAME_BAYES,
(char*)current_token->data, account_fullname,
NULL);
/* if the token/account is already in the tree, read the current
* value from the tree and use this for the basis of the value we
* are putting back
*/
if (value)
{
PINFO("found existing value of '%ld'\n",
(long)kvp_value_get_gint64(value));
/* convert this value back into an integer */
token_count += kvp_value_get_gint64(value);
}
/* increment the token count */
token_count++;
/* create a new value */
new_value = kvp_value_new_gint64(token_count);
/* insert the value into the kvp tree at
* /imap->frame/IMAP_FRAME/token_string/account_name_string
*/
kvp_frame_set_slot_path(imap->frame, new_value, IMAP_FRAME_BAYES,
(char*)current_token->data, account_fullname, NULL);
/* kvp_frame_set_slot_path() copied the value so we
* need to delete this one ;-) */
kvp_value_delete(new_value);
}
/* free up the account fullname string */
qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
xaccAccountCommitEdit (imap->acc);
g_free(account_fullname);
LEAVE(" ");
}
/** @} */

View File

@ -1,84 +0,0 @@
/********************************************************************\
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
* Boston, MA 02110-1301, USA gnu@gnu.org *
\********************************************************************/
/** @addtogroup Import_Export
@{ */
/** @file import-match-map.h
@brief Generic import mapper service, maps strings->accounts
*
An import mapper service that stores Account Maps for the
generic importer. This allows importers to map various
"strings" to Gnucash accounts in a generic manner.
@author Copyright (C) 2002,2003 Derek Atkins <derek@ihtfp.com>
*/
#ifndef GNC_IMPORT_MATCH_MAP_H
#define GNC_IMPORT_MATCH_MAP_H
typedef struct _GncImportMatchMap GncImportMatchMap;
#include "Account.h"
/** @{
Obtain an ImportMatchMap object from an Account or a Book */
GncImportMatchMap * gnc_imap_create_from_account (Account *acc);
GncImportMatchMap * gnc_imap_create_from_book (QofBook *book);
/*@}*/
/** Destroy an import map. But all stored entries will still continue
to exist in the underlying kvp frame of the account or book. */
void gnc_imap_destroy (GncImportMatchMap *imap);
/** Clear an import map -- this removes ALL entries in the map */
void gnc_imap_clear (GncImportMatchMap *imap);
/** Look up an Account in the map */
Account* gnc_imap_find_account(GncImportMatchMap *imap, const char* category,
const char *key);
/** Store an Account in the map. This mapping is immediatly stored in
the underlying kvp frame, regardless of whether the MatchMap is
destroyed later or not. */
void gnc_imap_add_account (GncImportMatchMap *imap, const char *category,
const char *key, Account *acc);
/** Look up an Account in the map from a GList* of pointers to strings(tokens)
from the current transaction */
Account* gnc_imap_find_account_bayes (GncImportMatchMap *imap, GList* tokens);
/** Store an Account in the map. This mapping is immediatly stored in
the underlying kvp frame, regardless of whether the MatchMap is
destroyed later or not. */
void gnc_imap_add_account_bayes (GncImportMatchMap *imap, GList* tokens,
Account *acc);
/** @name Some well-known categories
NOTE: You DO NOT have to use these values in your importer -- these
are just "well known" values, not "mandatory" values. You are free
to use these if they apply, map your own fields to these labels, or
create your own category strings.
*/
/** @{*/
#define GNCIMPORT_DESC "desc"
#define GNCIMPORT_MEMO "memo"
#define GNCIMPORT_PAYEE "payee"
/**@}*/
#endif /* GNC_IMPORT_MATCH_MAP_H */
/**@}*/

View File

@ -40,42 +40,36 @@
* Account, Transaction and Split
\********************************************************************/
const gchar * gnc_import_get_acc_online_id(Account * account)
const gchar * gnc_import_get_acc_online_id (Account * account)
{
kvp_frame * frame;
frame = xaccAccountGetSlots(account);
return kvp_frame_get_string(frame, "online_id");
gchar *id = NULL;
qof_instance_get (QOF_INSTANCE (account), "online-id", &id, NULL);
return id;
}
/* Used in the midst of editing a transaction; make it save the
* account data. */
void gnc_import_set_acc_online_id(Account * account,
const gchar * string_value)
void gnc_import_set_acc_online_id (Account *account, const gchar *id)
{
kvp_frame * frame;
g_return_if_fail (account != NULL);
frame = xaccAccountGetSlots(account);
xaccAccountBeginEdit (account);
kvp_frame_set_str(frame, "online_id", string_value);
qof_instance_set_dirty (QOF_INSTANCE (account));
qof_instance_set (QOF_INSTANCE (account), "online-id", &id, NULL);
xaccAccountCommitEdit (account);
}
const gchar * gnc_import_get_trans_online_id(Transaction * transaction)
const gchar * gnc_import_get_trans_online_id (Transaction * transaction)
{
kvp_frame * frame;
frame = xaccTransGetSlots(transaction);
return kvp_frame_get_string(frame, "online_id");
gchar *id = NULL;
qof_instance_get (QOF_INSTANCE (transaction), "online-id", &id, NULL);
return id;
}
/* Not actually used */
void gnc_import_set_trans_online_id(Transaction * transaction,
const gchar * string_value)
void gnc_import_set_trans_online_id (Transaction *transaction,
const gchar *id)
{
kvp_frame * frame;
g_return_if_fail (transaction != NULL);
xaccTransBeginEdit (transaction);
frame = xaccTransGetSlots(transaction);
kvp_frame_set_str (frame, "online_id", string_value);
qof_instance_set_dirty (QOF_INSTANCE (transaction));
qof_instance_set (QOF_INSTANCE (transaction), "online-id", &id, NULL);
xaccTransCommitEdit (transaction);
}
@ -86,24 +80,19 @@ gboolean gnc_import_trans_has_online_id(Transaction * transaction)
return (online_id != NULL && strlen(online_id) > 0);
}
const gchar * gnc_import_get_split_online_id(Split * split)
const gchar * gnc_import_get_split_online_id (Split * split)
{
kvp_frame * frame;
frame = xaccSplitGetSlots(split);
return kvp_frame_get_string(frame, "online_id");
gchar *id = NULL;
qof_instance_get (QOF_INSTANCE (split), "online-id", &id, NULL);
return id;
}
/* Used several places in a transaction edit where many other
* parameters are also being set, so individual commits wouldn't be
* appropriate. */
void gnc_import_set_split_online_id(Split * split,
const gchar * string_value)
* appropriate. Besides, there isn't a function for one.*/
void gnc_import_set_split_online_id (Split *split, const gchar *id)
{
kvp_frame * frame;
xaccTransBeginEdit (xaccSplitGetParent (split));
frame = xaccSplitGetSlots(split);
kvp_frame_set_str (frame, "online_id", string_value);
qof_instance_set_dirty (QOF_INSTANCE (split));
xaccTransCommitEdit (xaccSplitGetParent (split));
g_return_if_fail (split != NULL);
qof_instance_set (QOF_INSTANCE (split), "online-id", &id, NULL);
}
gboolean gnc_import_split_has_online_id(Split * split)

Some files were not shown because too many files have changed in this diff Show More