mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
-- Change gnc-trace.h to use the glib g_log() routine for all error
printing and tracing. -- ongoing cap-gains work git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@9290 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
499a4d5e76
commit
dff9fa3b3b
@ -39,6 +39,7 @@
|
||||
#include "gnc-lot.h"
|
||||
#include "gnc-lot-p.h"
|
||||
#include "gnc-pricedb.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "kvp_frame.h"
|
||||
#include "kvp-util-p.h"
|
||||
#include "messages.h"
|
||||
@ -1494,6 +1495,7 @@ xaccAccountSetCommodity (Account * acc, gnc_commodity * com)
|
||||
{
|
||||
acc->commodity = com;
|
||||
acc->commodity_scu = gnc_commodity_get_fraction(com);
|
||||
acc->non_standard_scu = FALSE;
|
||||
update_split_commodity(acc);
|
||||
|
||||
acc->sort_dirty = TRUE;
|
||||
@ -1502,25 +1504,13 @@ xaccAccountSetCommodity (Account * acc, gnc_commodity * com)
|
||||
mark_account (acc);
|
||||
}
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
if (gnc_commodity_is_iso(com)) {
|
||||
|
||||
if (gnc_commodity_is_iso(com))
|
||||
{
|
||||
/* compatability hack - Gnucash 1.8 gets currency quotes when a
|
||||
non-default currency is assigned to an account. */
|
||||
gnc_commodity_set_quote_flag(com, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xaccAccountSetCommoditySCU (Account *acc, int scu)
|
||||
{
|
||||
if (!acc) return;
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
{
|
||||
acc->commodity_scu = scu;
|
||||
mark_account (acc);
|
||||
}
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
@ -1531,7 +1521,7 @@ xaccAccountSetCommoditySCU (Account *acc, int scu)
|
||||
* to mismatched values in the past.
|
||||
*/
|
||||
void
|
||||
xaccAccountSetCommoditySCUandFlag (Account *acc, int scu)
|
||||
xaccAccountSetCommoditySCU (Account *acc, int scu)
|
||||
{
|
||||
if (!acc) return;
|
||||
|
||||
@ -1613,69 +1603,6 @@ DxaccAccountSetCurrency (Account * acc, gnc_commodity * currency)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DxaccAccountSetSecurity (Account *acc, gnc_commodity * security)
|
||||
{
|
||||
const char *string;
|
||||
gnc_commodity *commodity;
|
||||
|
||||
if ((!acc) || (!security)) return;
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
string = gnc_commodity_get_unique_name (security);
|
||||
kvp_frame_set_slot_nc(acc->kvp_data, "old-security",
|
||||
kvp_value_new_string(string));
|
||||
mark_account (acc);
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
|
||||
commodity = DxaccAccountGetSecurity (acc);
|
||||
if (!commodity)
|
||||
{
|
||||
gnc_commodity_table_insert (gnc_commodity_table_get_table (acc->book), security);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DxaccAccountSetCurrencySCU (Account * acc, int scu)
|
||||
{
|
||||
if (!acc) return;
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
kvp_frame_set_slot_nc(acc->kvp_data, "old-currency-scu",
|
||||
kvp_value_new_gint64(scu));
|
||||
mark_account (acc);
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
int
|
||||
DxaccAccountGetCurrencySCU (Account * acc)
|
||||
{
|
||||
KvpValue *v;
|
||||
|
||||
if (!acc) return 0;
|
||||
|
||||
v = kvp_frame_get_slot(acc->kvp_data, "old-currency-scu");
|
||||
if (v) return kvp_value_get_gint64 (v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
void
|
||||
xaccAccountDeleteOldData (Account *account)
|
||||
{
|
||||
if (!account) return;
|
||||
|
||||
kvp_frame_set_slot_nc (account->kvp_data, "old-currency", NULL);
|
||||
kvp_frame_set_slot_nc (account->kvp_data, "old-security", NULL);
|
||||
kvp_frame_set_slot_nc (account->kvp_data, "old-currency-scu", NULL);
|
||||
kvp_frame_set_slot_nc (account->kvp_data, "old-security-scu", NULL);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
@ -1833,26 +1760,6 @@ xaccAccountGetCommodity (Account *acc)
|
||||
return (acc->commodity);
|
||||
}
|
||||
|
||||
gnc_commodity *
|
||||
DxaccAccountGetSecurity (Account *acc)
|
||||
{
|
||||
KvpValue *v;
|
||||
const char *s;
|
||||
gnc_commodity_table *table;
|
||||
|
||||
if (!acc) return NULL;
|
||||
|
||||
v = kvp_frame_get_slot(acc->kvp_data, "old-security");
|
||||
if (!v) return NULL;
|
||||
|
||||
s = kvp_value_get_string (v);
|
||||
if (!s) return NULL;
|
||||
|
||||
table = gnc_commodity_table_get_table (acc->book);
|
||||
|
||||
return gnc_commodity_table_lookup_unique (table, s);
|
||||
}
|
||||
|
||||
gnc_numeric
|
||||
xaccAccountGetBalance (Account *acc)
|
||||
{
|
||||
|
@ -260,53 +260,71 @@ void xaccAccountSetAutoInterestXfer (Account *account, gboolean value);
|
||||
/** @} */
|
||||
|
||||
/* @name Account Commodity setters/getters
|
||||
* Accounts are used to store an amount of 'something', that 'something'
|
||||
* is called the 'commodity'. An account can only hold one kind of
|
||||
* commodity. The following are used to get and set the commodity,
|
||||
* and also to set the SCU, the 'Smallest Commodity Unit'.
|
||||
*
|
||||
* New commodity access routines.
|
||||
* Note that when we say that a 'split' holds an 'amount', that amount
|
||||
* is denominated in the account commodity. Do not confuse 'amount'
|
||||
* and 'value'. The 'value' of a split is the value of the amount
|
||||
* expressed in the currency fo the transaction. Thus, for example,
|
||||
* the 'amount' may be 12 apples, where the account commodity is
|
||||
* 'apples'. The value of these 12 apples may be 12 dollars, where
|
||||
* the transaction currency is 'dollars'.
|
||||
*
|
||||
* The account structure no longer stores two commodities ('currency'
|
||||
* and 'security'). Instead it stores only one commodity. This single
|
||||
* commodity is the one formerly known as 'security'. Use
|
||||
* xaccAccountSetCommodity() and xaccAccountGetCommodity() to set and
|
||||
* fetch it. (This transition has been done between version 1.6.x and
|
||||
* 1.7.0.)
|
||||
* The SCU is the 'Smallest Commodity Unit', signifying the smallest
|
||||
* non-zero amount that can be stored in the account. It is
|
||||
* represented as the integer denominator of a fraction. Thus,
|
||||
* for example, a SCU of 12 means that 1/12 of something is the
|
||||
* smallest amount that can be stored in the account. SCU's can
|
||||
* be any value; they do not need to be decimal. This allows
|
||||
* the use of accounts with unusual, non-decimal commodities and
|
||||
* currencies.
|
||||
*
|
||||
* Basically, the engine eliminates the 'currency' field of the
|
||||
* Account structure. Instead, the common currency is stored with the
|
||||
* transaction. The 'value' of a split is a translation of the
|
||||
* Split's 'amount' (which is the amount of the Account's commodity
|
||||
* involved) into the Transaction's balancing currency. */
|
||||
* Normally, the SCU is determined by the commodity of the account.
|
||||
* However, this default SCU can be over-ridden and set to an
|
||||
* account-specific value. This is account-specific value is
|
||||
* called the 'non-standard' value in the documentation below.
|
||||
*/
|
||||
/** @{ */
|
||||
|
||||
/** Set the account's commodity */
|
||||
void xaccAccountSetCommodity (Account *account, gnc_commodity *comm);
|
||||
/** Get the account's commodity
|
||||
*
|
||||
* This is from the new commodity access routines.
|
||||
*
|
||||
* The account structure no longer stores two commodities ('currency'
|
||||
* and 'security'). Instead it stores only one commodity. This single
|
||||
* commodity is the one formerly known as 'security'. Use
|
||||
* xaccAccountSetCommodity() and xaccAccountGetCommodity() to set and
|
||||
* fetch it. (This transition has been done between version 1.6.x and
|
||||
* 1.7.0.)
|
||||
*
|
||||
* Basically, the engine eliminates the 'currency' field of the
|
||||
* Account structure. Instead, the common currency is stored with the
|
||||
* transaction. The 'value' of a split is a translation of the
|
||||
* Split's 'amount' (which is the amount of the Account's commodity
|
||||
* involved) into the Transaction's balancing currency. */
|
||||
|
||||
/* deprecated do not use */
|
||||
#define DxaccAccountSetSecurity xaccAccountSetCommodity
|
||||
|
||||
/** Get the account's commodity */
|
||||
gnc_commodity * xaccAccountGetCommodity (Account *account);
|
||||
/** DOCUMENT ME! */
|
||||
|
||||
/* deprecated do not use */
|
||||
#define DxaccAccountGetSecurity xaccAccountGetCommodity
|
||||
|
||||
/** Return the SCU for the account. If a non-standard SCU has been
|
||||
* set for the account, that s returned; else the default SCU for
|
||||
* the account commodity is returned.
|
||||
*/
|
||||
int xaccAccountGetCommoditySCU (Account *account);
|
||||
/** DOCUMENT ME! */
|
||||
|
||||
/** Return the 'internal' SCU setting. This returns the over-ride
|
||||
* SCU for the account (which might not be set, and might be zero). */
|
||||
int xaccAccountGetCommoditySCUi (Account *account);
|
||||
/** DOCUMENT ME! */
|
||||
|
||||
/** Set the SCU for the account. Normally, this routine is not
|
||||
* required, as the default SCU for an account is given by its
|
||||
* commodity.
|
||||
*/
|
||||
void xaccAccountSetCommoditySCU (Account *account, int frac);
|
||||
/** DOCUMENT ME! */
|
||||
void xaccAccountSetCommoditySCUandFlag (Account *account, int frac);
|
||||
/** DOCUMENT ME! */
|
||||
|
||||
/* deprecated -- do not use for future development */
|
||||
#define xaccAccountSetCommoditySCUandFlag xaccAccountSetCommoditySCU
|
||||
|
||||
/** Set the flag indicating that this account uses a non-standard SCU. */
|
||||
void xaccAccountSetNonStdSCU (Account *account, gboolean flag);
|
||||
/** DOCUMENT ME! */
|
||||
|
||||
/** Return boolean, indicating whether this account uses a
|
||||
* non-standard SCU. */
|
||||
gboolean xaccAccountGetNonStdSCU (Account *account);
|
||||
/**@}*/
|
||||
|
||||
@ -406,10 +424,6 @@ gboolean xaccAccountHasAncestor (Account *account, Account *ancestor);
|
||||
/** @{ */
|
||||
KvpFrame * xaccAccountGetSlots (Account *account);
|
||||
void xaccAccountSetSlots_nc(Account *account, KvpFrame *frame);
|
||||
|
||||
/** Delete any old data in the account's kvp data.
|
||||
* This includes the old currency and security fields. */
|
||||
void xaccAccountDeleteOldData (Account *account);
|
||||
/** @} */
|
||||
|
||||
/* ------------------ */
|
||||
@ -679,38 +693,18 @@ void xaccClearMarkDownGr (AccountGroup *group, short val);
|
||||
* These two funcs take control of their gnc_commodity args. Don't free */
|
||||
void DxaccAccountSetCurrency (Account *account, gnc_commodity *currency);
|
||||
|
||||
/** @deprecated The current API associates only one thing with an
|
||||
* account: the 'commodity'. Use xaccAccountGetCommodity() to fetch
|
||||
* it.
|
||||
*
|
||||
* These two funcs take control of their gnc_commodity args. Don't free */
|
||||
void DxaccAccountSetSecurity (Account *account, gnc_commodity *security);
|
||||
|
||||
/** @deprecated The current API associates only one thing with an
|
||||
* account: the 'commodity'. Use xaccAccountGetCommodity() to fetch
|
||||
* it. */
|
||||
gnc_commodity * DxaccAccountGetCurrency (Account *account);
|
||||
|
||||
/** @deprecated The current API associates only one thing with an
|
||||
* account: the 'commodity'. Use xaccAccountGetCommodity() to fetch
|
||||
* it. */
|
||||
gnc_commodity * DxaccAccountGetSecurity (Account *account);
|
||||
|
||||
/** @deprecated The current API associates only one thing with an
|
||||
* account: the 'commodity'. Use xaccAccountGetCommodity() to fetch
|
||||
* it. */
|
||||
void DxaccAccountSetCurrencySCU (Account *account, int frac);
|
||||
/** @deprecated The current API associates only one thing with an
|
||||
* account: the 'commodity'. Use xaccAccountGetCommodity() to fetch
|
||||
* it. */
|
||||
int DxaccAccountGetCurrencySCU (Account *account);
|
||||
|
||||
/** Set the timezone to be used when interpreting the results from a
|
||||
* given Finance::Quote backend. Unfortunately, the upstream sources
|
||||
* don't label their output, so the user has to specify this bit.
|
||||
*
|
||||
* @deprecated Price quote information is now stored on the
|
||||
* commodity, not the account. */
|
||||
|
||||
void dxaccAccountSetQuoteTZ (Account *account, const char *tz);
|
||||
/** Get the timezone to be used when interpreting the results from a
|
||||
* given Finance::Quote backend. Unfortunately, the upstream sources
|
||||
|
@ -89,6 +89,7 @@
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-event-p.h"
|
||||
#include "messages.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "qofbook.h"
|
||||
#include "qofbook-p.h"
|
||||
#include "qofid-p.h"
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-event-p.h"
|
||||
#include "gnc-numeric.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "qofbackend.h"
|
||||
#include "qofbook.h"
|
||||
#include "qofbook-p.h"
|
||||
|
@ -20,6 +20,7 @@ libgncmod_engine_la_SOURCES = \
|
||||
SX-ttinfo.c \
|
||||
Scrub.c \
|
||||
Scrub2.c \
|
||||
Scrub3.c \
|
||||
TransLog.c \
|
||||
Transaction.c \
|
||||
cap-gains.c \
|
||||
@ -67,6 +68,7 @@ gncinclude_HEADERS = \
|
||||
QueryCore.h \
|
||||
Scrub.h \
|
||||
Scrub2.h \
|
||||
Scrub3.h \
|
||||
TransLog.h \
|
||||
Transaction.h \
|
||||
cap-gains.h \
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "gnc-lot-p.h"
|
||||
#include "gnc-pricedb.h"
|
||||
#include "gnc-pricedb-p.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "Group.h"
|
||||
#include "GroupP.h"
|
||||
#include "kvp-util-p.h"
|
||||
|
@ -35,11 +35,12 @@
|
||||
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-numeric.h"
|
||||
#include "gnc-lot.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "Account.h"
|
||||
#include "Query.h"
|
||||
#include "Transaction.h"
|
||||
#include "TransactionP.h"
|
||||
#include "gnc-lot.h"
|
||||
|
||||
static short module = MOD_QUERY;
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "gnc-engine.h"
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-event-p.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "guid.h"
|
||||
#include "messages.h"
|
||||
#include "qofbook.h"
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "gnc-engine-util.h"
|
||||
#include "messages.h"
|
||||
#include "gnc-commodity.h"
|
||||
#include "gnc-trace.h"
|
||||
|
||||
static short module = MOD_SCRUB;
|
||||
|
||||
@ -409,6 +410,118 @@ xaccTransScrubImbalance (Transaction *trans, AccountGroup *root,
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================ */
|
||||
/* The xaccTransFindCommonCurrency () method returns
|
||||
* a gnc_commodity indicating a currency denomination that all
|
||||
* of the splits in this transaction have in common, using the
|
||||
* old/obsolete currency/security fields of the split accounts.
|
||||
*/
|
||||
|
||||
static gnc_commodity *
|
||||
FindCommonExclSCurrency (SplitList *splits,
|
||||
gnc_commodity * ra, gnc_commodity * rb,
|
||||
Split *excl_split)
|
||||
{
|
||||
GList *node;
|
||||
|
||||
if (!splits) return NULL;
|
||||
|
||||
for (node = splits; node; node = node->next)
|
||||
{
|
||||
Split *s = node->data;
|
||||
gnc_commodity * sa, * sb;
|
||||
|
||||
if (s == excl_split) continue;
|
||||
|
||||
g_return_val_if_fail (s->acc, NULL);
|
||||
|
||||
sa = DxaccAccountGetCurrency (s->acc);
|
||||
sb = xaccAccountGetCommodity (s->acc);
|
||||
|
||||
if (ra && rb) {
|
||||
int aa = !gnc_commodity_equiv(ra,sa);
|
||||
int ab = !gnc_commodity_equiv(ra,sb);
|
||||
int ba = !gnc_commodity_equiv(rb,sa);
|
||||
int bb = !gnc_commodity_equiv(rb,sb);
|
||||
|
||||
if ( (!aa) && bb) rb = NULL;
|
||||
else
|
||||
if ( (!ab) && ba) rb = NULL;
|
||||
else
|
||||
if ( (!ba) && ab) ra = NULL;
|
||||
else
|
||||
if ( (!bb) && aa) ra = NULL;
|
||||
else
|
||||
if ( aa && bb && ab && ba ) { ra = NULL; rb = NULL; }
|
||||
|
||||
if (!ra) { ra = rb; rb = NULL; }
|
||||
}
|
||||
else
|
||||
if (ra && !rb) {
|
||||
int aa = !gnc_commodity_equiv(ra,sa);
|
||||
int ab = !gnc_commodity_equiv(ra,sb);
|
||||
if ( aa && ab ) ra = NULL;
|
||||
}
|
||||
|
||||
if ((!ra) && (!rb)) return NULL;
|
||||
}
|
||||
|
||||
return (ra);
|
||||
}
|
||||
|
||||
/* This is the wrapper for those calls (i.e. the older ones) which
|
||||
* don't exclude one split from the splitlist when looking for a
|
||||
* common currency.
|
||||
*/
|
||||
static gnc_commodity *
|
||||
FindCommonCurrency (GList *splits, gnc_commodity * ra, gnc_commodity * rb)
|
||||
{
|
||||
return FindCommonExclSCurrency(splits, ra, rb, NULL);
|
||||
}
|
||||
|
||||
static gnc_commodity *
|
||||
xaccTransFindOldCommonCurrency (Transaction *trans, QofBook *book)
|
||||
{
|
||||
gnc_commodity *ra, *rb, *retval;
|
||||
Split *split;
|
||||
|
||||
if (!trans) return NULL;
|
||||
|
||||
if (trans->splits == NULL) return NULL;
|
||||
|
||||
g_return_val_if_fail (book, NULL);
|
||||
|
||||
split = trans->splits->data;
|
||||
|
||||
if (!split || NULL == split->acc) return NULL;
|
||||
|
||||
ra = DxaccAccountGetCurrency (split->acc);
|
||||
rb = xaccAccountGetCommodity (split->acc);
|
||||
|
||||
retval = FindCommonCurrency (trans->splits, ra, rb);
|
||||
|
||||
/* Compare this value to what we think should be the 'right' value */
|
||||
if (!trans->common_currency)
|
||||
{
|
||||
trans->common_currency = retval;
|
||||
}
|
||||
else if (!gnc_commodity_equiv (retval,trans->common_currency))
|
||||
{
|
||||
PWARN ("expected common currency %s but found %s\n",
|
||||
gnc_commodity_get_unique_name (trans->common_currency),
|
||||
gnc_commodity_get_unique_name (retval));
|
||||
}
|
||||
|
||||
if (NULL == retval)
|
||||
{
|
||||
/* In every situation I can think of, this routine should return
|
||||
* common currency. So make note of this ... */
|
||||
PWARN ("unable to find a common currency, and that is strange.");
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* ================================================================ */
|
||||
|
||||
void
|
||||
@ -544,6 +657,17 @@ xaccAccountScrubCommodity (Account *account)
|
||||
|
||||
/* ================================================================ */
|
||||
|
||||
static void
|
||||
xaccAccountDeleteOldData (Account *account)
|
||||
{
|
||||
if (!account) return;
|
||||
|
||||
kvp_frame_set_slot_nc (account->kvp_data, "old-currency", NULL);
|
||||
kvp_frame_set_slot_nc (account->kvp_data, "old-security", NULL);
|
||||
kvp_frame_set_slot_nc (account->kvp_data, "old-currency-scu", NULL);
|
||||
kvp_frame_set_slot_nc (account->kvp_data, "old-security-scu", NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
scrub_trans_currency_helper (Transaction *t, gpointer data)
|
||||
{
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-lot.h"
|
||||
#include "gnc-lot-p.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "kvp-util-p.h"
|
||||
#include "messages.h"
|
||||
|
||||
|
172
src/engine/Scrub3.c
Normal file
172
src/engine/Scrub3.c
Normal file
@ -0,0 +1,172 @@
|
||||
/********************************************************************\
|
||||
* Scrub3.c -- Constrain Cap Gains to Track Sources of Gains *
|
||||
* *
|
||||
* 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 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
\********************************************************************/
|
||||
|
||||
/* @file Scrub3.c
|
||||
* @breif Constrain Cap Gains to Track Sources of Gains
|
||||
* @author Created by Linas Vepstas Sept 2003
|
||||
* @author Copyright (c) 2003 Linas Vepstas <linas@linas.org>
|
||||
*
|
||||
* Provides a set of functions and utilities for checking and
|
||||
* repairing ('scrubbing clean') the usage of Cap Gains
|
||||
* transactions in stock and commodity accounts.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "gnc-commodity.h"
|
||||
#include "gnc-engine.h"
|
||||
#include "gnc-numeric.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "kvp_frame.h"
|
||||
#include "Scrub3.h"
|
||||
#include "Transaction.h"
|
||||
#include "TransactionP.h"
|
||||
|
||||
static short module = MOD_LOT;
|
||||
|
||||
/* ================================================================= */
|
||||
|
||||
static KvpFrame *
|
||||
is_subsplit (Split *split)
|
||||
{
|
||||
KvpValue *kval;
|
||||
KvpFrame *ksub;
|
||||
|
||||
if (!split) return NULL;
|
||||
g_return_val_if_fail (split->parent, NULL);
|
||||
|
||||
/* If there are no sub-splits, then there's nothing to do. */
|
||||
kval = kvp_frame_get_slot (split->kvp_data, "lot-split");
|
||||
if (!kval) return NULL;
|
||||
|
||||
ksub = kvp_value_get_frame (kval);
|
||||
g_return_val_if_fail (ksub, NULL);
|
||||
|
||||
return ksub;
|
||||
}
|
||||
|
||||
/* ================================================================= */
|
||||
|
||||
void
|
||||
xaccScrubSubSplitPrice (Split *split)
|
||||
{
|
||||
gnc_numeric src_amt, src_val;
|
||||
SplitList *node;
|
||||
|
||||
if (NULL == is_subsplit (split)) return;
|
||||
|
||||
ENTER (" ");
|
||||
/* Get 'price' of the indicated split */
|
||||
src_amt = xaccSplitGetAmount (split);
|
||||
src_val = xaccSplitGetValue (split);
|
||||
|
||||
/* Loop over splits, adjust each so that it has the same
|
||||
* ratio (i.e. price). Change the value to get things
|
||||
* right; do not change the amount */
|
||||
for (node=split->parent->splits; node; node=node->next)
|
||||
{
|
||||
Split *s = node->data;
|
||||
Transaction *txn = s->parent;
|
||||
gnc_numeric dst_amt, dst_val, target_val;
|
||||
gnc_numeric delta;
|
||||
int scu;
|
||||
|
||||
/* Skip the reference split */
|
||||
if (s == split) continue;
|
||||
|
||||
scu = gnc_commodity_get_fraction (txn->common_currency);
|
||||
|
||||
dst_amt = xaccSplitGetAmount (s);
|
||||
dst_val = xaccSplitGetValue (s);
|
||||
target_val = gnc_numeric_mul (dst_amt, src_val,
|
||||
GNC_DENOM_AUTO, GNC_DENOM_REDUCE);
|
||||
target_val = gnc_numeric_div (target_val, src_amt,
|
||||
scu, GNC_DENOM_EXACT);
|
||||
|
||||
/* If the required price changes are 'small', do nothing.
|
||||
* That is a case that the user will have to deal with
|
||||
* manually. This routine is really intended only for
|
||||
* a gross level of synchronization.
|
||||
*/
|
||||
delta = gnc_numeric_sub_fixed (target_val, dst_val);
|
||||
delta = gnc_numeric_abs (delta);
|
||||
if (3 * delta.num < delta.denom) continue;
|
||||
|
||||
/* If the amount is small, pass on that too */
|
||||
if ((-2 < dst_amt.num) && (dst_amt.num < 2)) continue;
|
||||
|
||||
/* Make the actual adjustment */
|
||||
xaccTransBeginEdit (txn);
|
||||
xaccSplitSetValue (s, target_val);
|
||||
xaccTransCommitEdit (txn);
|
||||
}
|
||||
LEAVE (" ");
|
||||
}
|
||||
|
||||
/* ================================================================= */
|
||||
|
||||
#if LATER
|
||||
|
||||
static void
|
||||
merge_splits (Split *sa, Split *sb)
|
||||
{
|
||||
Transaction *txn;
|
||||
|
||||
txn = sa->parent;
|
||||
xaccTransBeginEdit (txn);
|
||||
/* whack kvp of b, remove gem kvp of a */
|
||||
/* whack memo etc. b */
|
||||
/* set reconsile to no */
|
||||
/* add amounts, values */
|
||||
|
||||
xaccTransCommitEdit (txn);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
xaccScrubMergeSubSplits (Split *split)
|
||||
{
|
||||
KvpFrame *sf;
|
||||
SplitList *node;
|
||||
GNCLot *lot;
|
||||
|
||||
sf = is_subsplit (split);
|
||||
if (!sf) return;
|
||||
|
||||
lot = xaccSplitGetLot (split);
|
||||
|
||||
ENTER (" ");
|
||||
for (node=split->parent->splits; node; node=node->next)
|
||||
{
|
||||
Split *s = node->data;
|
||||
if (xaccSplitGetLot (s) != lot) continue;
|
||||
|
||||
/* OK, this split is in the same lot (and thus same account)
|
||||
* as the indicated split. It must be a subsplit. Merge the
|
||||
* two back together again. */
|
||||
}
|
||||
LEAVE (" ");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ========================== END OF FILE ========================= */
|
54
src/engine/Scrub3.h
Normal file
54
src/engine/Scrub3.h
Normal file
@ -0,0 +1,54 @@
|
||||
/********************************************************************\
|
||||
* Scrub3.h -- Constrain Cap Gains to Track Sources of Gains *
|
||||
* *
|
||||
* 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 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
\********************************************************************/
|
||||
|
||||
/** @addtogroup Engine
|
||||
@{ */
|
||||
/** @file Scrub3.h
|
||||
* @breif Constrain Cap Gains to Track Sources of Gains
|
||||
* @author Created by Linas Vepstas Sept 2003
|
||||
* @author Copyright (c) 2003 Linas Vepstas <linas@linas.org>
|
||||
*
|
||||
* Provides a set of functions and utilities for checking and
|
||||
* repairing ('scrubbing clean') the usage of Cap Gains
|
||||
* transactions in stock and commodity accounts.
|
||||
*/
|
||||
#ifndef XACC_SCRUB3_H
|
||||
#define XACC_SCRUB3_H
|
||||
|
||||
#include "gnc-engine.h"
|
||||
|
||||
/** If a split has been pulled apart to make it fit into two (or more)
|
||||
* lots, then it becomes theoretically possible for each subsplit to
|
||||
* have a distinct price. But this would be wrong: each subsplit should
|
||||
* have the same price, within rounding errors. This routine will
|
||||
* examine the indicated split for sub-splits, and adjust the value
|
||||
* of each so that they all have the same price.
|
||||
*
|
||||
* There is a bit of a problem with the interpretation of 'rounding
|
||||
* errors' because there are pathological corner cases of small
|
||||
* amounts. So this routine is fairly loose, hopefully loose enough
|
||||
* so that the user can manually fine tune without having this routine
|
||||
* clobber thier work.
|
||||
*/
|
||||
void xaccScrubSubSplitPrice (Split *split);
|
||||
|
||||
#endif /* XACC_SCRUB3_H */
|
||||
/** @} */
|
@ -43,6 +43,7 @@
|
||||
#include "gnc-event-p.h"
|
||||
#include "gnc-lot-p.h"
|
||||
#include "gnc-lot.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "messages.h"
|
||||
|
||||
#include "qofbackend-p.h"
|
||||
@ -66,23 +67,6 @@
|
||||
* of the GUI should ignore the data until its commited.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The "force_double_entry" flag determines how
|
||||
* the splits in a transaction will be balanced.
|
||||
*
|
||||
* The following values have significance:
|
||||
* 0 -- anything goes
|
||||
* 1 -- The sum of all splits in a transaction will be
|
||||
* forced to be zero, even if this requires the
|
||||
* creation of additional splits. Note that a split
|
||||
* whose value is zero (e.g. a stock price) can exist
|
||||
* by itself. Otherwise, all splits must come in at
|
||||
* least pairs.
|
||||
* 2 -- splits without parents will be forced into a
|
||||
* lost & found account. (Not implemented)
|
||||
*/
|
||||
int force_double_entry = 0;
|
||||
|
||||
const char *trans_notes_str = "notes";
|
||||
const char *void_reason_str = "void-reason";
|
||||
const char *void_time_str = "void-time";
|
||||
@ -510,21 +494,6 @@ xaccSplitLookupDirect (GUID guid, QofBook *book)
|
||||
&guid, GNC_ID_SPLIT);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
void
|
||||
xaccConfigSetForceDoubleEntry (int force)
|
||||
{
|
||||
force_double_entry = force;
|
||||
}
|
||||
|
||||
int
|
||||
xaccConfigGetForceDoubleEntry (void)
|
||||
{
|
||||
return (force_double_entry);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
/* Routines for marking splits dirty, and for sending out change
|
||||
@ -730,6 +699,7 @@ void
|
||||
DxaccSplitSetSharePriceAndAmount (Split *s, double price, double amt)
|
||||
{
|
||||
if (!s) return;
|
||||
ENTER (" ");
|
||||
check_open (s->parent);
|
||||
|
||||
s->amount = double_to_gnc_numeric(amt, get_commodity_denom(s),
|
||||
@ -747,6 +717,7 @@ xaccSplitSetSharePriceAndAmount (Split *s, gnc_numeric price,
|
||||
gnc_numeric amt)
|
||||
{
|
||||
if (!s) return;
|
||||
ENTER (" ");
|
||||
check_open (s->parent);
|
||||
|
||||
s->amount = gnc_numeric_convert(amt, get_commodity_denom(s), GNC_RND_ROUND);
|
||||
@ -762,6 +733,7 @@ void
|
||||
xaccSplitSetSharePrice (Split *s, gnc_numeric price)
|
||||
{
|
||||
if (!s) return;
|
||||
ENTER (" ");
|
||||
check_open (s->parent);
|
||||
|
||||
s->value = gnc_numeric_mul(xaccSplitGetAmount(s),
|
||||
@ -781,6 +753,7 @@ DxaccSplitSetShareAmount (Split *s, double damt)
|
||||
gnc_numeric amt = double_to_gnc_numeric(damt, commodity_denom,
|
||||
GNC_RND_ROUND);
|
||||
if (!s) return;
|
||||
ENTER (" ");
|
||||
check_open (s->parent);
|
||||
|
||||
old_amt = xaccSplitGetAmount (s);
|
||||
@ -809,6 +782,8 @@ void
|
||||
xaccSplitSetAmount (Split *s, gnc_numeric amt)
|
||||
{
|
||||
if(!s) return;
|
||||
ENTER ("old amt=%lld/%lld new amt=%lld/%lld",
|
||||
s->amount.num, s->amount.denom, amt.num, amt.denom);
|
||||
check_open (s->parent);
|
||||
|
||||
s->amount = gnc_numeric_convert(amt, get_commodity_denom(s), GNC_RND_ROUND);
|
||||
@ -823,6 +798,8 @@ void
|
||||
xaccSplitSetValue (Split *s, gnc_numeric amt)
|
||||
{
|
||||
if(!s) return;
|
||||
ENTER ("old val=%lld/%lld new val=%lld/%lld",
|
||||
s->value.num, s->value.denom, amt.num, amt.denom);
|
||||
check_open (s->parent);
|
||||
|
||||
s->value = gnc_numeric_convert(amt, get_currency_denom(s), GNC_RND_ROUND);
|
||||
@ -1373,25 +1350,9 @@ xaccSplitSetBaseValue (Split *s, gnc_numeric value,
|
||||
if (!s) return;
|
||||
check_open (s->parent);
|
||||
|
||||
/* Novice/casual users may not want or use the double entry
|
||||
* features of this engine. So, in particular, there may be the
|
||||
* occasional split without a parent account. Well, that's ok,
|
||||
* we'll just go with the flow. */
|
||||
if (NULL == s->acc)
|
||||
{
|
||||
if (force_double_entry)
|
||||
{
|
||||
PERR ("split must have a parent\n");
|
||||
g_return_if_fail (s->acc);
|
||||
}
|
||||
else
|
||||
{
|
||||
s->value = value;
|
||||
s->amount = value;
|
||||
SET_GAINS_A_VDIRTY(s);
|
||||
}
|
||||
mark_split (s);
|
||||
/* gen_event (s); No! only in TransCommit() ! */
|
||||
PERR ("split must have a parent\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1415,10 +1376,6 @@ xaccSplitSetBaseValue (Split *s, gnc_numeric value,
|
||||
s->amount = gnc_numeric_convert(value, get_commodity_denom(s),
|
||||
GNC_RND_NEVER);
|
||||
}
|
||||
else if ((NULL==base_currency) && (0 == force_double_entry)) {
|
||||
s->value = gnc_numeric_convert(value, get_currency_denom(s),
|
||||
GNC_RND_NEVER);
|
||||
}
|
||||
else {
|
||||
PERR ("inappropriate base currency %s "
|
||||
"given split currency=%s and commodity=%s\n",
|
||||
@ -1443,20 +1400,9 @@ xaccSplitGetBaseValue (const Split *s,
|
||||
|
||||
if (!s) return gnc_numeric_zero();
|
||||
|
||||
/* ahh -- users may not want or use the double entry
|
||||
* features of this engine. So, in particular, there
|
||||
* may be the occasional split without a parent account.
|
||||
* Well, that's ok, we'll just go with the flow.
|
||||
*/
|
||||
if (NULL == s->acc)
|
||||
{
|
||||
if (force_double_entry)
|
||||
{
|
||||
g_return_val_if_fail (s->acc, gnc_numeric_zero ());
|
||||
}
|
||||
else {
|
||||
return xaccSplitGetValue((Split *)s);
|
||||
}
|
||||
g_return_val_if_fail (s->acc, gnc_numeric_zero ());
|
||||
}
|
||||
|
||||
currency = xaccTransGetCurrency (s->parent);
|
||||
@ -1472,10 +1418,6 @@ xaccSplitGetBaseValue (const Split *s,
|
||||
{
|
||||
value = xaccSplitGetAmount (s);
|
||||
}
|
||||
else if ((NULL == base_currency) && (0 == force_double_entry))
|
||||
{
|
||||
value = xaccSplitGetValue(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
PERR ("inappropriate base currency %s "
|
||||
@ -1497,78 +1439,64 @@ xaccSplitsComputeValue (GList *splits, Split * skip_me,
|
||||
const gnc_commodity * base_currency)
|
||||
{
|
||||
GList *node;
|
||||
gnc_numeric value;
|
||||
gnc_numeric value = gnc_numeric_zero();
|
||||
|
||||
g_return_val_if_fail (base_currency, value);
|
||||
|
||||
ENTER (" currency=%s", gnc_commodity_get_mnemonic (base_currency));
|
||||
value = gnc_numeric_zero();
|
||||
|
||||
for (node = splits; node; node = node->next)
|
||||
{
|
||||
Split *s = node->data;
|
||||
const gnc_commodity *currency;
|
||||
const gnc_commodity *commodity;
|
||||
|
||||
if (s == skip_me) continue;
|
||||
|
||||
/* ahh -- users may not want or use the double entry features of
|
||||
* this engine. So, in particular, there may be the occasional
|
||||
* split without a parent account. Well, that's ok, we'll just
|
||||
* go with the flow. */
|
||||
/* The split-editor often sends us 'temp' splits whose account
|
||||
* hasn't yet been set. Be lenient, and assume an implied base
|
||||
* currency. If theres a problem later, teh scrub routines will
|
||||
* pick it up.
|
||||
*/
|
||||
if (NULL == s->acc)
|
||||
{
|
||||
if (force_double_entry)
|
||||
{
|
||||
g_return_val_if_fail (s->acc, gnc_numeric_zero ());
|
||||
}
|
||||
else
|
||||
{
|
||||
value = gnc_numeric_add(value, xaccSplitGetValue(s),
|
||||
GNC_DENOM_AUTO, GNC_DENOM_LCD);
|
||||
}
|
||||
commodity = base_currency;
|
||||
}
|
||||
else if ((NULL == base_currency) && (0 == force_double_entry))
|
||||
else
|
||||
{
|
||||
commodity = xaccAccountGetCommodity (s->acc);
|
||||
}
|
||||
|
||||
currency = xaccTransGetCurrency (s->parent);
|
||||
|
||||
if (gnc_commodity_equiv(currency, base_currency))
|
||||
{
|
||||
value = gnc_numeric_add(value, xaccSplitGetValue(s),
|
||||
GNC_DENOM_AUTO, GNC_DENOM_LCD);
|
||||
}
|
||||
else
|
||||
else if (gnc_commodity_equiv(commodity, base_currency))
|
||||
{
|
||||
const gnc_commodity *currency;
|
||||
const gnc_commodity *commodity;
|
||||
|
||||
currency = xaccTransGetCurrency (s->parent);
|
||||
commodity = xaccAccountGetCommodity (s->acc);
|
||||
|
||||
/* OK, we've got a parent account, we've got currency, lets
|
||||
* behave like professionals now, instead of the shenanigans
|
||||
* above. Note that just because the currencies are equivalent
|
||||
* doesn't mean the denominators are the same! */
|
||||
if (base_currency &&
|
||||
gnc_commodity_equiv(currency, base_currency)) {
|
||||
value = gnc_numeric_add(value, xaccSplitGetValue(s),
|
||||
GNC_DENOM_AUTO, GNC_DENOM_LCD);
|
||||
}
|
||||
else if (base_currency &&
|
||||
gnc_commodity_equiv(commodity, base_currency)) {
|
||||
value = gnc_numeric_add(value, xaccSplitGetAmount(s),
|
||||
GNC_DENOM_AUTO, GNC_DENOM_LCD);
|
||||
}
|
||||
else {
|
||||
PERR ("inconsistent currencies\n"
|
||||
"\tbase = '%s', curr='%s', sec='%s'\n",
|
||||
gnc_commodity_get_printname(base_currency),
|
||||
gnc_commodity_get_printname(currency),
|
||||
gnc_commodity_get_printname(commodity));
|
||||
g_return_val_if_fail (FALSE, gnc_numeric_zero ());
|
||||
}
|
||||
value = gnc_numeric_add(value, xaccSplitGetAmount(s),
|
||||
GNC_DENOM_AUTO, GNC_DENOM_LCD);
|
||||
}
|
||||
else {
|
||||
PERR ("inconsistent currencies\n"
|
||||
"\tbase = '%s', curr='%s', sec='%s'\n",
|
||||
gnc_commodity_get_printname(base_currency),
|
||||
gnc_commodity_get_printname(currency),
|
||||
gnc_commodity_get_printname(commodity));
|
||||
g_return_val_if_fail (FALSE, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (base_currency)
|
||||
return gnc_numeric_convert (value,
|
||||
/* Note that just because the currencies are equivalent
|
||||
* doesn't mean the denominators are the same! */
|
||||
value = gnc_numeric_convert (value,
|
||||
gnc_commodity_get_fraction (base_currency),
|
||||
GNC_RND_ROUND);
|
||||
else
|
||||
return gnc_numeric_convert (value, GNC_DENOM_AUTO, GNC_DENOM_REDUCE);
|
||||
LEAVE (" ");
|
||||
|
||||
LEAVE (" total=%lld/%lld", value.num, value.denom);
|
||||
return value;
|
||||
}
|
||||
|
||||
gnc_numeric
|
||||
@ -1602,126 +1530,6 @@ xaccTransGetAccountValue (const Transaction *trans,
|
||||
return total;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
static gnc_commodity *
|
||||
FindCommonExclSCurrency (SplitList *splits,
|
||||
gnc_commodity * ra, gnc_commodity * rb,
|
||||
Split *excl_split)
|
||||
{
|
||||
GList *node;
|
||||
|
||||
if (!splits) return NULL;
|
||||
|
||||
for (node = splits; node; node = node->next)
|
||||
{
|
||||
Split *s = node->data;
|
||||
gnc_commodity * sa, * sb;
|
||||
|
||||
if (s == excl_split) continue;
|
||||
|
||||
/* Novice/casual users may not want or use the double entry
|
||||
* features of this engine. Because of this, there
|
||||
* may be the occasional split without a parent account.
|
||||
* Well, that's ok, we'll just go with the flow.
|
||||
*/
|
||||
if (force_double_entry)
|
||||
{
|
||||
g_return_val_if_fail (s->acc, NULL);
|
||||
}
|
||||
else if (NULL == s->acc)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sa = DxaccAccountGetCurrency (s->acc);
|
||||
sb = DxaccAccountGetSecurity (s->acc);
|
||||
|
||||
if (ra && rb) {
|
||||
int aa = !gnc_commodity_equiv(ra,sa);
|
||||
int ab = !gnc_commodity_equiv(ra,sb);
|
||||
int ba = !gnc_commodity_equiv(rb,sa);
|
||||
int bb = !gnc_commodity_equiv(rb,sb);
|
||||
|
||||
if ( (!aa) && bb) rb = NULL;
|
||||
else
|
||||
if ( (!ab) && ba) rb = NULL;
|
||||
else
|
||||
if ( (!ba) && ab) ra = NULL;
|
||||
else
|
||||
if ( (!bb) && aa) ra = NULL;
|
||||
else
|
||||
if ( aa && bb && ab && ba ) { ra = NULL; rb = NULL; }
|
||||
|
||||
if (!ra) { ra = rb; rb = NULL; }
|
||||
}
|
||||
else
|
||||
if (ra && !rb) {
|
||||
int aa = !gnc_commodity_equiv(ra,sa);
|
||||
int ab = !gnc_commodity_equiv(ra,sb);
|
||||
if ( aa && ab ) ra = NULL;
|
||||
}
|
||||
|
||||
if ((!ra) && (!rb)) return NULL;
|
||||
}
|
||||
|
||||
return (ra);
|
||||
}
|
||||
|
||||
/* This is the wrapper for those calls (i.e. the older ones) which
|
||||
* don't exclude one split from the splitlist when looking for a
|
||||
* common currency.
|
||||
*/
|
||||
static gnc_commodity *
|
||||
FindCommonCurrency (GList *splits, gnc_commodity * ra, gnc_commodity * rb)
|
||||
{
|
||||
return FindCommonExclSCurrency(splits, ra, rb, NULL);
|
||||
}
|
||||
|
||||
gnc_commodity *
|
||||
xaccTransFindOldCommonCurrency (Transaction *trans, QofBook *book)
|
||||
{
|
||||
gnc_commodity *ra, *rb, *retval;
|
||||
Split *split;
|
||||
|
||||
if (!trans) return NULL;
|
||||
|
||||
if (trans->splits == NULL) return NULL;
|
||||
|
||||
g_return_val_if_fail (book, NULL);
|
||||
|
||||
split = trans->splits->data;
|
||||
|
||||
if (!split || NULL == split->acc) return NULL;
|
||||
|
||||
ra = DxaccAccountGetCurrency (split->acc);
|
||||
rb = DxaccAccountGetSecurity (split->acc);
|
||||
|
||||
retval = FindCommonCurrency (trans->splits, ra, rb);
|
||||
|
||||
/* compare this value to what we think should be the 'right' value */
|
||||
if (!trans->common_currency)
|
||||
{
|
||||
trans->common_currency = retval;
|
||||
}
|
||||
else if (!gnc_commodity_equiv (retval,trans->common_currency))
|
||||
{
|
||||
PWARN ("expected common currency %s but found %s\n",
|
||||
gnc_commodity_get_unique_name (trans->common_currency),
|
||||
gnc_commodity_get_unique_name (retval));
|
||||
}
|
||||
|
||||
if (NULL == retval)
|
||||
{
|
||||
/* in every situation I can think of, this routine should return
|
||||
* common currency. So make note of this ... */
|
||||
PWARN ("unable to find a common currency, and that is strange.");
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
/* The new routine for setting the common currency */
|
||||
@ -1910,16 +1718,20 @@ xaccTransCommitEdit (Transaction *trans)
|
||||
trans->date_entered.tv_nsec = 1000 * tv.tv_usec;
|
||||
}
|
||||
|
||||
#if SCRUB_BEFORE_COMMITTING
|
||||
/* XXX the below is a weak attempt to scrub the transaction
|
||||
* before committing it. Not clear if this is a good idea
|
||||
* or not, since the scrubbers can run independently/in parallel.
|
||||
*/
|
||||
/* Alternately the transaction may have only one split in
|
||||
* it, in which case that's OK if and only if the split has no
|
||||
* value (i.e. is only recording a price). Otherwise, a single
|
||||
* split with a value can't possibly balance, thus violating the
|
||||
* rules of double-entry, and that's way bogus. So create
|
||||
* a matching opposite and place it either here (if force==1),
|
||||
* or in some dummy account (if force==2).
|
||||
* a matching opposite and place it here.
|
||||
* XXX should be using Scrub routine to do this correctly ...
|
||||
*/
|
||||
if ((1 == force_double_entry) &&
|
||||
(NULL == g_list_nth(trans->splits, 1)) &&
|
||||
if ((NULL == g_list_nth(trans->splits, 1)) &&
|
||||
(!gnc_numeric_zero_p(xaccSplitGetAmount(split))))
|
||||
{
|
||||
Split * s = xaccMallocSplit(trans->book);
|
||||
@ -1931,6 +1743,7 @@ xaccTransCommitEdit (Transaction *trans)
|
||||
xaccSplitSetAction (s, split->action);
|
||||
SET_GAINS_A_VDIRTY(s);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ------------------------------------------------- */
|
||||
@ -3398,25 +3211,54 @@ xaccGetAccountByFullName (Transaction *trans, const char * name,
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
/* In the old world, the 'other split' was the other split of a
|
||||
* transaction that contained only two splits. In the new world,
|
||||
* a split may have been cut up between multiple lots, although
|
||||
* in a conceptual sense, if lots hadn't been used, there would be
|
||||
* only a pair. So we handle this conceptual case: we can still
|
||||
* identify, unambiguously, the 'other' split when 'this' split
|
||||
* as been cut up across lots. We do thins by looking for the
|
||||
* 'lot-split' keyword, which occurs only in cut-up splits.
|
||||
*/
|
||||
|
||||
Split *
|
||||
xaccSplitGetOtherSplit (const Split *split)
|
||||
{
|
||||
Split *s1, *s2;
|
||||
SplitList *node;
|
||||
Transaction *trans;
|
||||
int count;
|
||||
Split *other = NULL;
|
||||
KvpValue *sva;
|
||||
|
||||
if (!split) return NULL;
|
||||
trans = split->parent;
|
||||
if (!trans) return NULL;
|
||||
|
||||
#ifdef OLD_ALGO_HAS_ONLY_TWO_SPLITS
|
||||
Split *s1, *s2;
|
||||
if (g_list_length (trans->splits) != 2) return NULL;
|
||||
|
||||
s1 = g_list_nth_data (trans->splits, 0);
|
||||
s2 = g_list_nth_data (trans->splits, 1);
|
||||
|
||||
if (s1 == split) return s2;
|
||||
|
||||
return s1;
|
||||
#endif
|
||||
|
||||
count = g_list_length (trans->splits);
|
||||
sva = kvp_frame_get_slot (split->kvp_data, "lot-split");
|
||||
if (!sva && (2 != count)) return NULL;
|
||||
|
||||
for (node=trans->splits; node; node=node->next)
|
||||
{
|
||||
Split *s = node->data;
|
||||
KvpValue *va = kvp_frame_get_slot (s->kvp_data, "lot-split");
|
||||
if (s == split) { --count; continue; }
|
||||
if (va) { --count; continue; }
|
||||
other = s;
|
||||
}
|
||||
if (1 == count) return other;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
|
@ -57,39 +57,6 @@
|
||||
#define TXN_TYPE_PAYMENT 'P' /**< Transaction is a payment */
|
||||
/**@}*/
|
||||
|
||||
|
||||
/** @name Configuration ForceDoubleEntry getters/setters
|
||||
*/
|
||||
/**@{*/
|
||||
/**
|
||||
* The xaccConfigSetForceDoubleEntry() and xaccConfigGetForceDoubleEntry()
|
||||
* set and get the "force_double_entry" flag. This flag determines how
|
||||
* the splits in a transaction will be balanced.
|
||||
*
|
||||
* The following values have significance:
|
||||
*
|
||||
* 0 -- anything goes
|
||||
*
|
||||
* 1 -- The sum of all splits in a transaction will be
|
||||
* forced to be zero, even if this requires the
|
||||
* creation of additional splits. Note that a split
|
||||
* whose value is zero (e.g. a stock price) can exist
|
||||
* by itself. Otherwise, all splits must come in at
|
||||
* least pairs.
|
||||
*
|
||||
* 2 -- splits without parents will be forced into a
|
||||
* lost & found account. (Not implemented)
|
||||
*/
|
||||
void xaccConfigSetForceDoubleEntry (int force);
|
||||
/**
|
||||
* The xaccConfigSetForceDoubleEntry() and xaccConfigGetForceDoubleEntry()
|
||||
* set and get the "force_double_entry" flag. This flag determines how
|
||||
* the splits in a transaction will be balanced.
|
||||
*/
|
||||
int xaccConfigGetForceDoubleEntry (void);
|
||||
/**@}*/
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* Transaction
|
||||
*/
|
||||
|
@ -289,14 +289,6 @@ void DxaccSplitSetSharePriceAndAmount (Split *split,
|
||||
double amount);
|
||||
void DxaccSplitSetShareAmount (Split *split, double amount);
|
||||
|
||||
/* The deprecated xaccTransFindCommonCurrency () method returns
|
||||
* a gnc_commodity indicating a currency denomination that all
|
||||
* of the splits in this transaction have in common, using the
|
||||
* old currency/security fields of the split accounts. DO NOT
|
||||
* USE THIS ROUTINE! */
|
||||
gnc_commodity * xaccTransFindOldCommonCurrency (Transaction *trans,
|
||||
QofBook *book);
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
||||
|
@ -75,6 +75,7 @@ ToDo List:
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-lot.h"
|
||||
#include "gnc-lot-p.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "kvp-util-p.h"
|
||||
#include "messages.h"
|
||||
#include "qofid-p.h"
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-engine.h"
|
||||
#include "gnc-numeric.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "guile-mappings.h"
|
||||
#include "qofbook.h"
|
||||
#include "qofquery.h"
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "gnc-associate-account.h"
|
||||
#include "gnc-engine.h"
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "qofbook.h"
|
||||
#include "qofid.h"
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
|
||||
#include "gnc-date.h"
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-trace.h"
|
||||
|
||||
#ifndef HAVE_STRPTIME
|
||||
#include "strptime.h"
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include <glib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "gnc-trace.h"
|
||||
#include "gnc-trace.h" // XXX eliminate me eventually
|
||||
|
||||
/** Macros *****************************************************/
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-event-p.h"
|
||||
#include "gnc-trace.h"
|
||||
|
||||
|
||||
/** Declarations ****************************************************/
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "gnc-event-p.h"
|
||||
#include "gnc-lot.h"
|
||||
#include "gnc-lot-p.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "Transaction.h"
|
||||
#include "TransactionP.h"
|
||||
#include "qofqueryobject.h"
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-event-p.h"
|
||||
#include "gnc-pricedb-p.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "guid.h"
|
||||
#include "kvp-util.h"
|
||||
#include "qofbackend-p.h"
|
||||
|
@ -35,10 +35,10 @@
|
||||
/* This static indicates the debugging module that this .o belongs to. */
|
||||
/* static short module = MOD_ENGINE; */
|
||||
|
||||
static gncLogLevel loglevel[MOD_LAST + 1] =
|
||||
gncLogLevel gnc_log_modules[MOD_LAST + 1] =
|
||||
{
|
||||
GNC_LOG_FATAL, /* DUMMY */
|
||||
GNC_LOG_WARNING, /* ENGINE */
|
||||
GNC_LOG_TRACE, /* ENGINE */
|
||||
GNC_LOG_WARNING, /* IO */
|
||||
GNC_LOG_WARNING, /* REGISTER */
|
||||
GNC_LOG_WARNING, /* LEDGER */
|
||||
@ -47,16 +47,16 @@ static gncLogLevel loglevel[MOD_LAST + 1] =
|
||||
GNC_LOG_WARNING, /* SCRUB */
|
||||
GNC_LOG_WARNING, /* GTK_REG */
|
||||
GNC_LOG_WARNING, /* GUILE */
|
||||
GNC_LOG_WARNING, /* BACKEND */
|
||||
GNC_LOG_WARNING, /* QUERY */
|
||||
GNC_LOG_TRACE, /* BACKEND */
|
||||
GNC_LOG_TRACE, /* QUERY */
|
||||
GNC_LOG_WARNING, /* PRICE */
|
||||
GNC_LOG_WARNING, /* SQL EVENT */
|
||||
GNC_LOG_WARNING, /* SQL TXN */
|
||||
GNC_LOG_WARNING, /* KVP */
|
||||
GNC_LOG_WARNING, /* SX */
|
||||
GNC_LOG_WARNING, /* BOOK */
|
||||
GNC_LOG_TRACE, /* BOOK */
|
||||
GNC_LOG_TRACE, /* TEST */
|
||||
GNC_LOG_WARNING, /* LOT */
|
||||
GNC_LOG_TRACE, /* LOT */
|
||||
GNC_LOG_WARNING, /* ACCOUNT */
|
||||
GNC_LOG_WARNING, /* IMPORT */
|
||||
GNC_LOG_WARNING, /* BUSINESS */
|
||||
@ -66,6 +66,24 @@ static gncLogLevel loglevel[MOD_LAST + 1] =
|
||||
|
||||
static FILE *fout = NULL;
|
||||
|
||||
static void
|
||||
fh_printer (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
FILE *fh = user_data;
|
||||
fprintf (fh, "%s\n", message);
|
||||
}
|
||||
|
||||
void
|
||||
gnc_log_init (void)
|
||||
{
|
||||
fout = stderr;
|
||||
fout = stdout;
|
||||
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, fh_printer, fout);
|
||||
}
|
||||
|
||||
/* Set the logging level of the given module. */
|
||||
void
|
||||
gnc_set_log_level(gncModuleType module, gncLogLevel level)
|
||||
@ -73,7 +91,7 @@ gnc_set_log_level(gncModuleType module, gncLogLevel level)
|
||||
if ((module < 0) || (module > MOD_LAST))
|
||||
return;
|
||||
|
||||
loglevel[module] = level;
|
||||
gnc_log_modules[module] = level;
|
||||
}
|
||||
|
||||
/* Set the logging level for all modules. */
|
||||
@ -83,7 +101,7 @@ gnc_set_log_level_global(gncLogLevel level)
|
||||
gncModuleType module;
|
||||
|
||||
for (module = 0; module <= MOD_LAST; module++)
|
||||
loglevel[module] = level;
|
||||
gnc_log_modules[module] = level;
|
||||
}
|
||||
|
||||
void
|
||||
@ -92,13 +110,13 @@ gnc_set_logfile (FILE *outfile)
|
||||
fout = outfile;
|
||||
}
|
||||
|
||||
/* prettify() cleans up subroutine names. AIX/xlC has the habit of
|
||||
* printing signatures not names; clean this up. On other operating
|
||||
/* gnc_log_prettify() cleans up subroutine names. AIX/xlC has the habit
|
||||
* of printing signatures not names; clean this up. On other operating
|
||||
* systems, truncate name to 30 chars. Note this routine is not thread
|
||||
* safe. Note we wouldn't need this routine if AIX did something more
|
||||
* reasonable. Hope thread safety doesn't poke us in eye. */
|
||||
static const char *
|
||||
prettify (const char *name)
|
||||
const char *
|
||||
gnc_log_prettify (const char *name)
|
||||
{
|
||||
static char bf[128];
|
||||
char *p;
|
||||
@ -120,46 +138,6 @@ prettify (const char *name)
|
||||
return bf;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gnc_should_log (gncModuleType module, gncLogLevel log_level)
|
||||
{
|
||||
if (module < 0 || module > MOD_LAST)
|
||||
{
|
||||
PERR ("Bad module: %d", module);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (log_level > loglevel[module])
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_log (gncModuleType module, gncLogLevel log_level, const char *prefix,
|
||||
const char *function_name, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (!gnc_should_log (module, log_level))
|
||||
return;
|
||||
|
||||
if (!fout) fout = stderr;
|
||||
|
||||
fprintf (fout, "%s: %s: ",
|
||||
prefix ? prefix : "(null)",
|
||||
prettify (function_name));
|
||||
|
||||
va_start (ap, format);
|
||||
|
||||
vfprintf (fout, format, ap);
|
||||
|
||||
va_end (ap);
|
||||
|
||||
fprintf (fout, "\n");
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
@ -187,10 +165,10 @@ gnc_start_clock (int clockno, gncModuleType module, gncLogLevel log_level,
|
||||
if ((0>clockno) || (NUM_CLOCKS <= clockno)) return;
|
||||
gettimeofday (&gnc_clock[clockno], &tz);
|
||||
|
||||
if (!fout) fout = stderr;
|
||||
if (!fout) gnc_log_init();
|
||||
|
||||
fprintf (fout, "Clock %d Start: %s: ",
|
||||
clockno, prettify (function_name));
|
||||
clockno, gnc_log_prettify (function_name));
|
||||
|
||||
va_start (ap, format);
|
||||
|
||||
@ -224,10 +202,10 @@ gnc_report_clock (int clockno, gncModuleType module, gncLogLevel log_level,
|
||||
gnc_clock_total[clockno].tv_sec += now.tv_sec;
|
||||
gnc_clock_total[clockno].tv_usec += now.tv_usec;
|
||||
|
||||
if (!fout) fout = stderr;
|
||||
if (!fout) gnc_log_init();
|
||||
|
||||
fprintf (fout, "Clock %d Elapsed: %ld.%06lds %s: ",
|
||||
clockno, now.tv_sec, now.tv_usec, prettify (function_name));
|
||||
clockno, now.tv_sec, now.tv_usec, gnc_log_prettify (function_name));
|
||||
|
||||
va_start (ap, format);
|
||||
|
||||
@ -254,13 +232,13 @@ gnc_report_clock_total (int clockno,
|
||||
gnc_clock_total[clockno].tv_usec -= 1000000;
|
||||
}
|
||||
|
||||
if (!fout) fout = stderr;
|
||||
if (!fout) gnc_log_init();
|
||||
|
||||
fprintf (fout, "Clock %d Total Elapsed: %ld.%06lds %s: ",
|
||||
clockno,
|
||||
gnc_clock_total[clockno].tv_sec,
|
||||
gnc_clock_total[clockno].tv_usec,
|
||||
prettify (function_name));
|
||||
gnc_log_prettify (function_name));
|
||||
|
||||
va_start (ap, format);
|
||||
|
||||
@ -278,12 +256,14 @@ gnc_report_clock_total (int clockno,
|
||||
static GNCGuiMessage gnc_gui_warning_func = NULL;
|
||||
static GNCGuiMessage gnc_gui_error_func = NULL;
|
||||
|
||||
void gnc_set_warning_message (GNCGuiMessage func)
|
||||
void
|
||||
gnc_set_warning_message (GNCGuiMessage func)
|
||||
{
|
||||
gnc_gui_warning_func = func;
|
||||
}
|
||||
|
||||
void gnc_set_error_message (GNCGuiMessage func)
|
||||
void
|
||||
gnc_set_error_message (GNCGuiMessage func)
|
||||
{
|
||||
gnc_gui_error_func = func;
|
||||
}
|
||||
@ -293,10 +273,17 @@ gnc_send_gui_warning(const gchar *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
if (!gnc_gui_warning_func)
|
||||
return(FALSE);
|
||||
{
|
||||
if (!fout) gnc_log_init();
|
||||
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||||
format, args);
|
||||
va_end (args);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
va_start(args, format);
|
||||
gnc_gui_warning_func(format, args);
|
||||
va_end(args);
|
||||
return(TRUE);
|
||||
@ -307,10 +294,17 @@ gnc_send_gui_error(const gchar *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
if (!gnc_gui_error_func)
|
||||
return(FALSE);
|
||||
{
|
||||
if (!fout) gnc_log_init();
|
||||
|
||||
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
|
||||
format, args);
|
||||
va_end (args);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
va_start(args, format);
|
||||
gnc_gui_error_func(format, args);
|
||||
va_end(args);
|
||||
return(TRUE);
|
||||
|
@ -76,93 +76,128 @@ typedef enum
|
||||
GNC_LOG_TRACE = 6,
|
||||
} gncLogLevel;
|
||||
|
||||
extern gncLogLevel gnc_log_modules[MOD_LAST + 1];
|
||||
|
||||
/** Initialize the error logging subsystem */
|
||||
void gnc_log_init (void);
|
||||
|
||||
/** Set the logging level of the given module. */
|
||||
void gnc_set_log_level(gncModuleType module, gncLogLevel level);
|
||||
|
||||
/** Set the logging level for all modules. */
|
||||
void gnc_set_log_level_global(gncLogLevel level);
|
||||
|
||||
/** Specify an alternate log output, to pipe or file. By default,
|
||||
* all logging goes to STDERR. */
|
||||
void gnc_set_logfile (FILE *outfile);
|
||||
|
||||
|
||||
/** gnc_log_prettify() cleans up subroutine names. AIX/xlC has the habit
|
||||
* of printing signatures not names; clean this up. On other operating
|
||||
* systems, truncate name to 30 chars. Note this routine is not thread
|
||||
* safe. Note we wouldn't need this routine if AIX did something more
|
||||
* reasonable. Hope thread safety doesn't poke us in eye. */
|
||||
const char * gnc_log_prettify (const char *name);
|
||||
|
||||
/* We want logging decisions to be made inline, rather than through
|
||||
* a CPU-cucking subroutine call. Thus, this is a #define, not a
|
||||
* subroutine call. The prototype would have been:
|
||||
* gboolean gnc_should_log (gncModuleType module, gncLogLevel log_level);
|
||||
*/
|
||||
#define gnc_should_log(module,log_level) \
|
||||
(log_level <= gnc_log_modules[module])
|
||||
|
||||
#define FUNK gnc_log_prettify(__FUNCTION__)
|
||||
|
||||
/** Log error/waring/info messages to stderr or to other pipe.
|
||||
* This logging infrastructure is meant for validating the
|
||||
* correctness of the execution of the code. 'Info' level
|
||||
* messages help trace program flow. 'Error' messages are
|
||||
* meant to indicate internal data inconsistencies.
|
||||
*
|
||||
* Messages can be logged to stdout, stderr, or to any desired
|
||||
* FILE * file handle. Use fdopen() to get a file handle from a
|
||||
* file descriptor. Use gnc_set_logfile to set the logging file
|
||||
* handle.
|
||||
*/
|
||||
|
||||
#define FATAL(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_FATAL)) { \
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, \
|
||||
"Fatal Error: %s: " format, FUNK, ## args); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PERR(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_ERROR)) { \
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
|
||||
"Error: %s: " format, FUNK, ## args); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PWARN(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_WARNING)) { \
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, \
|
||||
"Warning: %s: " format, FUNK, ## args); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PWARN_GUI(format, args...) { \
|
||||
gnc_send_gui_error(format, ## args); \
|
||||
}
|
||||
|
||||
#define PINFO(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_INFO)) { \
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, \
|
||||
"Info: %s: " format, FUNK, ## args); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DEBUG(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_DEBUG)) { \
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
|
||||
"Debug: %s: " format, FUNK, ## args); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ENTER(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_DEBUG)) { \
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
|
||||
"Enter: %s: " format, FUNK, ## args); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LEAVE(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_DEBUG)) { \
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
|
||||
"Leave: %s: " format, FUNK, ## args); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define TRACE(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_TRACE)) { \
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
|
||||
"Trace: %s: " format, FUNK, ## args); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DEBUGCMD(x) { if (gnc_should_log (module, GNC_LOG_DEBUG)) { (x); }}
|
||||
|
||||
/* -------------------------------------------------------- */
|
||||
/* Infrastructure to send messages go to GUI popups, not to stderr!
|
||||
* Incompletely implemented, needs work.
|
||||
*/
|
||||
typedef void (*GNCGuiMessage) (const char *format, va_list args);
|
||||
void gnc_set_warning_message (GNCGuiMessage func);
|
||||
void gnc_set_error_message (GNCGuiMessage func);
|
||||
|
||||
gboolean gnc_send_gui_warning (const char *format, ...);
|
||||
gboolean gnc_send_gui_error (const char *format, ...);
|
||||
gboolean gnc_send_gui_warning (const char *format, ...) G_GNUC_PRINTF(1,2);
|
||||
gboolean gnc_send_gui_error (const char *format, ...) G_GNUC_PRINTF(1,2);
|
||||
|
||||
/* FIXME: these logging functions should proably get replaced by
|
||||
* the glib.h g_error(), etc functions. That way, we would have
|
||||
* unified logging mechanism, instead of having some messages
|
||||
* work one way, and other a different way ...
|
||||
*
|
||||
* FIXME: the if test should not be a subroutine call, it should
|
||||
* not use that many CPU cycles. These logging functions are supposed
|
||||
* to be lightweight. Who changed this ??? Why ???
|
||||
*
|
||||
/* -------------------------------------------------------- */
|
||||
/* Infrastructure to make timing measurements for critical peices
|
||||
* of code. Used for only for performance tuning & debugging.
|
||||
*/
|
||||
gboolean gnc_should_log (gncModuleType module, gncLogLevel log_level);
|
||||
void gnc_log (gncModuleType module, gncLogLevel log_level,
|
||||
const char *prefix, const char *function_name,
|
||||
const char *format, ...) G_GNUC_PRINTF(5,6);
|
||||
|
||||
#define FATAL(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_FATAL)) \
|
||||
gnc_log (module, GNC_LOG_FATAL, "Fatal Error", \
|
||||
__FUNCTION__, format, ## args); \
|
||||
}
|
||||
|
||||
#define PERR(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_ERROR)) \
|
||||
gnc_log (module, GNC_LOG_ERROR, "Error", \
|
||||
__FUNCTION__, format, ##args); \
|
||||
}
|
||||
|
||||
#define PWARN(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_WARNING)) \
|
||||
gnc_log (module, GNC_LOG_WARNING, "Warning", \
|
||||
__FUNCTION__, format, ## args); \
|
||||
}
|
||||
|
||||
#define PWARN_GUI(format, args...) { \
|
||||
if (!gnc_send_gui_error(format, ## args)) \
|
||||
PWARN(format, ## args); \
|
||||
}
|
||||
|
||||
#define PINFO(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_INFO)) \
|
||||
gnc_log (module, GNC_LOG_INFO, "Info", \
|
||||
__FUNCTION__, format, ## args); \
|
||||
}
|
||||
|
||||
#define DEBUG(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_DEBUG)) \
|
||||
gnc_log (module, GNC_LOG_DEBUG, "Debug", \
|
||||
__FUNCTION__, format, ## args); \
|
||||
}
|
||||
|
||||
#define ENTER(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_DEBUG)) \
|
||||
gnc_log (module, GNC_LOG_DEBUG, "Enter", \
|
||||
__FUNCTION__, format, ## args); \
|
||||
}
|
||||
|
||||
#define LEAVE(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_DEBUG)) \
|
||||
gnc_log (module, GNC_LOG_DEBUG, "Leave", \
|
||||
__FUNCTION__, format, ## args); \
|
||||
}
|
||||
|
||||
#define DETAIL(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_DETAIL)) \
|
||||
gnc_log (module, GNC_LOG_DETAIL, "Detail", \
|
||||
__FUNCTION__, format, ## args); \
|
||||
}
|
||||
|
||||
|
||||
#define DEBUGCMD(x) { if (gnc_should_log (module, GNC_LOG_DEBUG)) { x; }}
|
||||
|
||||
#define ERROR() fprintf(stderr,"%s: Line %d, error = %s\n", \
|
||||
__FILE__, __LINE__, strerror(errno));
|
||||
|
||||
#define TRACE(format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_TRACE)) \
|
||||
gnc_log (module, GNC_LOG_TRACE, "Trace", \
|
||||
__FUNCTION__, format, ## args); \
|
||||
}
|
||||
|
||||
void gnc_start_clock (int clockno, gncModuleType module, gncLogLevel log_level,
|
||||
const char *function_name, const char *format, ...);
|
||||
@ -179,16 +214,16 @@ void gnc_report_clock_total (int clockno,
|
||||
const char *function_name,
|
||||
const char *format, ...);
|
||||
|
||||
#define START_CLOCK(clockno,format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_INFO)) \
|
||||
gnc_start_clock (clockno, module, GNC_LOG_INFO,\
|
||||
__FUNCTION__, format, ## args); \
|
||||
#define START_CLOCK(clockno,format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_INFO)) \
|
||||
gnc_start_clock (clockno, module, GNC_LOG_INFO, \
|
||||
__FUNCTION__, format, ## args); \
|
||||
}
|
||||
|
||||
#define REPORT_CLOCK(clockno,format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_INFO)) \
|
||||
gnc_report_clock (clockno, module, GNC_LOG_INFO,\
|
||||
__FUNCTION__, format, ## args); \
|
||||
#define REPORT_CLOCK(clockno,format, args...) { \
|
||||
if (gnc_should_log (module, GNC_LOG_INFO)) \
|
||||
gnc_report_clock (clockno, module, GNC_LOG_INFO, \
|
||||
__FUNCTION__, format, ## args); \
|
||||
}
|
||||
|
||||
#define REPORT_CLOCK_TOTAL(clockno,format, args...) { \
|
||||
@ -197,13 +232,4 @@ void gnc_report_clock_total (int clockno,
|
||||
__FUNCTION__, format, ## args); \
|
||||
}
|
||||
|
||||
/* Set the logging level of the given module. */
|
||||
void gnc_set_log_level(gncModuleType module, gncLogLevel level);
|
||||
|
||||
/* Set the logging level for all modules. */
|
||||
void gnc_set_log_level_global(gncLogLevel level);
|
||||
|
||||
/* Pipe log output to pipe or file */
|
||||
void gnc_set_logfile (FILE *outfile);
|
||||
|
||||
#endif /* GNC_TRACE_H */
|
||||
|
@ -23,21 +23,22 @@
|
||||
(list
|
||||
"#include <glib.h>\n"
|
||||
"#include <guid.h>\n"
|
||||
"#include <Query.h>\n"
|
||||
"#include <Group.h>\n"
|
||||
"#include <Query.h>\n"
|
||||
"#include <gnc-commodity.h>\n"
|
||||
"#include <gnc-date.h>\n"
|
||||
"#include <gnc-engine.h>\n"
|
||||
"#include <gnc-engine-util.h>\n"
|
||||
"#include <gnc-event.h>\n"
|
||||
"#include <gnc-numeric.h>\n"
|
||||
"#include <gnc-pricedb.h>\n"
|
||||
"#include <gnc-lot.h>\n"
|
||||
"#include <gnc-trace.h>\n"
|
||||
"#include <gnc-session-scm.h>\n"
|
||||
"#include <qofbackend.h>\n"
|
||||
"#include <qofbook.h>\n"
|
||||
"#include <qofsession.h>\n"
|
||||
"#include <gnc-session-scm.h>\n"
|
||||
"#include <gnc-engine-util.h>\n"
|
||||
"#include <gnc-event.h>\n"
|
||||
"#include <gnc-pricedb.h>\n"
|
||||
"#include <gnc-lot.h>\n"
|
||||
"#include <gnc-date.h>\n"
|
||||
"#include <engine-helpers.h>\n"
|
||||
"#include <gnc-engine.h>\n"
|
||||
"#include <gnc-commodity.h>\n"
|
||||
"#include <gnc-numeric.h>\n")))
|
||||
"#include <engine-helpers.h>\n")))
|
||||
|
||||
(gw:wrapset-add-cs-initializers!
|
||||
ws
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "gnc-date.h"
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-numeric.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "guid.h"
|
||||
#include "kvp_frame.h"
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "qofid.h"
|
||||
#include "qofid-p.h"
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-trace.h"
|
||||
|
||||
#define CACHE_INSERT(str) g_cache_insert(gnc_engine_get_string_cache(), (gpointer)(str));
|
||||
#define CACHE_REMOVE(str) g_cache_remove(gnc_engine_get_string_cache(), (gpointer)(str));
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <glib.h>
|
||||
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "qofobject.h"
|
||||
#include "qofobject-p.h"
|
||||
#include "qofbook.h"
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-trace.h"
|
||||
|
||||
#include "qofbackend-p.h"
|
||||
#include "qofbook.h"
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <glib.h>
|
||||
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "qofquery.h"
|
||||
#include "qofquerycore.h"
|
||||
#include "qofquerycore-p.h"
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <glib.h>
|
||||
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-trace.h"
|
||||
#include "qofqueryobject-p.h"
|
||||
#include "qofquery.h"
|
||||
|
||||
|
@ -272,7 +272,7 @@ static void
|
||||
qof_session_int_backend_load_error(QofSession *session,
|
||||
char *message, char *dll_err)
|
||||
{
|
||||
PWARN (message, dll_err ? dll_err : "");
|
||||
PWARN ("%s %s", message, dll_err ? dll_err : "");
|
||||
|
||||
g_free(session->fullpath);
|
||||
session->fullpath = NULL;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <glib.h>
|
||||
#include <libguile.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "guid.h"
|
||||
#include "gnc-module.h"
|
||||
|
Loading…
Reference in New Issue
Block a user