2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************\
|
|
|
|
* Scrub.c -- convert single-entry accounts into clean double-entry *
|
|
|
|
* *
|
|
|
|
* 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 *
|
2005-11-16 23:35:02 -06:00
|
|
|
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
|
|
|
|
* Boston, MA 02110-1301, USA gnu@gnu.org *
|
2001-08-07 18:36:04 -05:00
|
|
|
* *
|
|
|
|
\********************************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FILE:
|
|
|
|
* Scrub.c
|
|
|
|
*
|
|
|
|
* FUNCTION:
|
2010-03-02 15:40:28 -06:00
|
|
|
* Provides a set of functions and utilities for scrubbing clean
|
|
|
|
* single-entry accounts so that they can be promoted into
|
2001-08-07 18:36:04 -05:00
|
|
|
* self-consistent, clean double-entry accounts.
|
|
|
|
*
|
|
|
|
* HISTORY:
|
|
|
|
* Created by Linas Vepstas December 1998
|
2003-03-30 23:15:21 -06:00
|
|
|
* Copyright (c) 1998-2000, 2003 Linas Vepstas <linas@linas.org>
|
|
|
|
* Copyright (c) 2002 Christian Stimming
|
2006-04-15 13:50:59 -05:00
|
|
|
* Copyright (c) 2006 David Hampton
|
2001-08-07 18:36:04 -05:00
|
|
|
*/
|
|
|
|
|
2017-10-26 04:14:21 -05:00
|
|
|
#include <config.h>
|
2001-08-07 18:36:04 -05:00
|
|
|
|
|
|
|
#include <glib.h>
|
2005-11-19 17:53:34 -06:00
|
|
|
#include <glib/gi18n.h>
|
2001-08-07 18:36:04 -05:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2018-11-11 02:29:06 -06:00
|
|
|
#include <stdint.h>
|
2001-08-07 18:36:04 -05:00
|
|
|
|
|
|
|
#include "Account.h"
|
2003-03-30 21:25:19 -06:00
|
|
|
#include "AccountP.h"
|
2001-08-07 18:36:04 -05:00
|
|
|
#include "Scrub.h"
|
|
|
|
#include "Transaction.h"
|
|
|
|
#include "TransactionP.h"
|
2003-01-25 05:07:42 -06:00
|
|
|
#include "gnc-commodity.h"
|
2017-11-09 15:33:58 -06:00
|
|
|
#include "qofinstance-p.h"
|
2021-05-04 12:11:59 -05:00
|
|
|
#include "gnc-session.h"
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2007-12-15 16:24:05 -06:00
|
|
|
#undef G_LOG_DOMAIN
|
|
|
|
#define G_LOG_DOMAIN "gnc.engine.scrub"
|
|
|
|
|
|
|
|
static QofLogModule log_module = G_LOG_DOMAIN;
|
2020-08-22 18:11:17 -05:00
|
|
|
static gboolean abort_now = FALSE;
|
|
|
|
static gint scrub_depth = 0;
|
|
|
|
|
2021-01-26 16:56:29 -06:00
|
|
|
|
|
|
|
static Account* xaccScrubUtilityGetOrMakeAccount (Account *root,
|
|
|
|
gnc_commodity* currency,
|
|
|
|
const char* accname,
|
|
|
|
GNCAccountType acctype,
|
2021-01-26 18:16:25 -06:00
|
|
|
gboolean placeholder,
|
|
|
|
gboolean checkname);
|
2021-01-26 16:56:29 -06:00
|
|
|
|
2020-08-22 18:11:17 -05:00
|
|
|
void
|
|
|
|
gnc_set_abort_scrub (gboolean abort)
|
|
|
|
{
|
|
|
|
abort_now = abort;
|
|
|
|
}
|
|
|
|
|
2020-10-20 08:42:32 -05:00
|
|
|
gboolean
|
|
|
|
gnc_get_abort_scrub (void)
|
|
|
|
{
|
|
|
|
return abort_now;
|
|
|
|
}
|
|
|
|
|
2020-08-22 18:11:17 -05:00
|
|
|
gboolean
|
|
|
|
gnc_get_ongoing_scrub (void)
|
|
|
|
{
|
|
|
|
return scrub_depth > 0;
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
|
|
|
/* ================================================================ */
|
|
|
|
|
|
|
|
void
|
2016-11-06 10:10:30 -06:00
|
|
|
xaccAccountTreeScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!acc) return;
|
2020-10-20 08:43:39 -05:00
|
|
|
|
|
|
|
if (abort_now)
|
|
|
|
(percentagefunc)(NULL, -1.0);
|
|
|
|
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth ++;
|
2016-11-06 10:10:30 -06:00
|
|
|
xaccAccountScrubOrphans (acc, percentagefunc);
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_account_foreach_descendant(acc,
|
2016-11-06 10:10:30 -06:00
|
|
|
(AccountCb)xaccAccountScrubOrphans, percentagefunc);
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth--;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2003-04-04 23:38:12 -06:00
|
|
|
static void
|
2007-02-22 19:23:31 -06:00
|
|
|
TransScrubOrphansFast (Transaction *trans, Account *root)
|
2003-04-04 23:38:12 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *node;
|
|
|
|
gchar *accname;
|
2003-04-04 23:38:12 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans) return;
|
|
|
|
g_return_if_fail (root);
|
2021-05-04 15:20:01 -05:00
|
|
|
g_return_if_fail (trans->common_currency);
|
2003-04-04 23:38:12 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
for (node = trans->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
Split *split = node->data;
|
|
|
|
Account *orph;
|
2020-08-22 18:11:17 -05:00
|
|
|
if (abort_now) break;
|
2003-04-04 23:38:12 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (split->acc) continue;
|
2003-04-04 23:38:12 -06:00
|
|
|
|
2021-02-18 00:30:53 -06:00
|
|
|
DEBUG ("Found an orphan\n");
|
2003-04-04 23:38:12 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
accname = g_strconcat (_("Orphan"), "-",
|
|
|
|
gnc_commodity_get_mnemonic (trans->common_currency),
|
|
|
|
NULL);
|
|
|
|
orph = xaccScrubUtilityGetOrMakeAccount (root, trans->common_currency,
|
2021-01-26 18:16:25 -06:00
|
|
|
accname, ACCT_TYPE_BANK,
|
|
|
|
FALSE, TRUE);
|
2010-03-02 15:40:28 -06:00
|
|
|
g_free (accname);
|
|
|
|
if (!orph) continue;
|
2003-04-04 23:38:12 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccSplitSetAccount(split, orph);
|
|
|
|
}
|
2003-04-04 23:38:12 -06:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
void
|
2016-11-06 10:10:30 -06:00
|
|
|
xaccAccountScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2016-11-06 10:10:30 -06:00
|
|
|
GList *node, *splits;
|
2010-03-02 15:40:28 -06:00
|
|
|
const char *str;
|
2016-11-06 10:10:30 -06:00
|
|
|
const char *message = _( "Looking for orphans in account %s: %u of %u");
|
|
|
|
guint total_splits = 0;
|
|
|
|
guint current_split = 0;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!acc) return;
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth++;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
str = xaccAccountGetName (acc);
|
|
|
|
str = str ? str : "(null)";
|
2021-02-18 00:30:53 -06:00
|
|
|
PINFO ("Looking for orphans in account %s\n", str);
|
2016-11-06 10:10:30 -06:00
|
|
|
splits = xaccAccountGetSplitList(acc);
|
|
|
|
total_splits = g_list_length (splits);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2016-11-06 10:10:30 -06:00
|
|
|
for (node = splits; node; node = node->next)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
Split *split = node->data;
|
2020-09-06 09:52:13 -05:00
|
|
|
if (current_split % 10 == 0)
|
2016-11-06 10:10:30 -06:00
|
|
|
{
|
|
|
|
char *progress_msg = g_strdup_printf (message, str, current_split, total_splits);
|
|
|
|
(percentagefunc)(progress_msg, (100 * current_split) / total_splits);
|
|
|
|
g_free (progress_msg);
|
2020-08-22 18:11:17 -05:00
|
|
|
if (abort_now) break;
|
2016-11-06 10:10:30 -06:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
TransScrubOrphansFast (xaccSplitGetParent (split),
|
|
|
|
gnc_account_get_root (acc));
|
2016-11-06 10:10:30 -06:00
|
|
|
current_split++;
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
2016-11-06 10:10:30 -06:00
|
|
|
(percentagefunc)(NULL, -1.0);
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth--;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2003-04-04 23:38:12 -06:00
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
void
|
2003-04-04 23:38:12 -06:00
|
|
|
xaccTransScrubOrphans (Transaction *trans)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
SplitList *node;
|
|
|
|
QofBook *book = NULL;
|
|
|
|
Account *root = NULL;
|
2014-12-20 05:10:20 -06:00
|
|
|
|
|
|
|
if (!trans) return;
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
for (node = trans->splits; node; node = node->next)
|
2003-04-04 23:38:12 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
Split *split = node->data;
|
2020-08-22 18:11:17 -05:00
|
|
|
if (abort_now) break;
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
if (split->acc)
|
|
|
|
{
|
|
|
|
TransScrubOrphansFast (trans, gnc_account_get_root(split->acc));
|
|
|
|
return;
|
|
|
|
}
|
2003-04-04 23:38:12 -06:00
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
/* If we got to here, then *none* of the splits belonged to an
|
|
|
|
* account. Not a happy situation. We should dig an account
|
|
|
|
* out of the book the transaction belongs to.
|
|
|
|
* XXX we should probably *always* to this, instead of the above loop!
|
|
|
|
*/
|
|
|
|
PINFO ("Free Floating Transaction!");
|
|
|
|
book = xaccTransGetBook (trans);
|
|
|
|
root = gnc_book_get_root_account (book);
|
|
|
|
TransScrubOrphansFast (trans, root);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ================================================================ */
|
|
|
|
|
|
|
|
void
|
|
|
|
xaccAccountTreeScrubSplits (Account *account)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!account) return;
|
2007-02-22 19:23:31 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccAccountScrubSplits (account);
|
|
|
|
gnc_account_foreach_descendant(account,
|
|
|
|
(AccountCb)xaccAccountScrubSplits, NULL);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xaccAccountScrubSplits (Account *account)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *node;
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth++;
|
2010-03-02 15:40:28 -06:00
|
|
|
for (node = xaccAccountGetSplitList (account); node; node = node->next)
|
2020-08-22 18:11:17 -05:00
|
|
|
{
|
|
|
|
if (abort_now) break;
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccSplitScrub (node->data);
|
2020-08-22 18:11:17 -05:00
|
|
|
}
|
|
|
|
scrub_depth--;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xaccSplitScrub (Split *split)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
Account *account;
|
|
|
|
Transaction *trans;
|
|
|
|
gnc_numeric value, amount;
|
|
|
|
gnc_commodity *currency, *acc_commodity;
|
|
|
|
int scu;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!split) return;
|
|
|
|
ENTER ("(split=%p)", split);
|
|
|
|
|
|
|
|
trans = xaccSplitGetParent (split);
|
|
|
|
if (!trans)
|
|
|
|
{
|
|
|
|
LEAVE("no trans");
|
|
|
|
return;
|
|
|
|
}
|
2003-04-04 23:38:12 -06:00
|
|
|
|
|
|
|
account = xaccSplitGetAccount (split);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* If there's no account, this split is an orphan.
|
|
|
|
* We need to fix that first, before proceeding.
|
|
|
|
*/
|
|
|
|
if (!account)
|
|
|
|
{
|
|
|
|
xaccTransScrubOrphans (trans);
|
|
|
|
account = xaccSplitGetAccount (split);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Grrr... the register gnc_split_register_load() line 203 of
|
|
|
|
* src/register/ledger-core/split-register-load.c will create
|
|
|
|
* free-floating bogus transactions. Ignore these for now ...
|
|
|
|
*/
|
|
|
|
if (!account)
|
|
|
|
{
|
|
|
|
PINFO ("Free Floating Transaction!");
|
|
|
|
LEAVE ("no account");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Split amounts and values should be valid numbers */
|
|
|
|
value = xaccSplitGetValue (split);
|
|
|
|
if (gnc_numeric_check (value))
|
|
|
|
{
|
|
|
|
value = gnc_numeric_zero();
|
|
|
|
xaccSplitSetValue (split, value);
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
amount = xaccSplitGetAmount (split);
|
|
|
|
if (gnc_numeric_check (amount))
|
|
|
|
{
|
|
|
|
amount = gnc_numeric_zero();
|
|
|
|
xaccSplitSetAmount (split, amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
currency = xaccTransGetCurrency (trans);
|
|
|
|
|
|
|
|
/* If the account doesn't have a commodity,
|
|
|
|
* we should attempt to fix that first.
|
2015-10-11 23:49:53 -05:00
|
|
|
*/
|
2010-03-02 15:40:28 -06:00
|
|
|
acc_commodity = xaccAccountGetCommodity(account);
|
|
|
|
if (!acc_commodity)
|
|
|
|
{
|
|
|
|
xaccAccountScrubCommodity (account);
|
|
|
|
}
|
|
|
|
if (!acc_commodity || !gnc_commodity_equiv(acc_commodity, currency))
|
|
|
|
{
|
|
|
|
LEAVE ("(split=%p) inequiv currency", split);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
scu = MIN (xaccAccountGetCommoditySCU (account),
|
|
|
|
gnc_commodity_get_fraction (currency));
|
|
|
|
|
2010-10-23 05:38:48 -05:00
|
|
|
if (gnc_numeric_same (amount, value, scu, GNC_HOW_RND_ROUND_HALF_UP))
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
LEAVE("(split=%p) different values", split);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This will be hit every time you answer yes to the dialog "The
|
|
|
|
* current transaction has changed. Would you like to record it.
|
|
|
|
*/
|
|
|
|
PINFO ("Adjusted split with mismatched values, desc=\"%s\" memo=\"%s\""
|
|
|
|
" old amount %s %s, new amount %s",
|
|
|
|
trans->description, split->memo,
|
|
|
|
gnc_num_dbg_to_string (xaccSplitGetAmount(split)),
|
|
|
|
gnc_commodity_get_mnemonic (currency),
|
|
|
|
gnc_num_dbg_to_string (xaccSplitGetValue(split)));
|
|
|
|
|
|
|
|
xaccTransBeginEdit (trans);
|
|
|
|
xaccSplitSetAmount (split, value);
|
|
|
|
xaccTransCommitEdit (trans);
|
|
|
|
LEAVE ("(split=%p)", split);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ================================================================ */
|
|
|
|
|
|
|
|
void
|
2016-11-06 10:10:30 -06:00
|
|
|
xaccAccountTreeScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2020-10-20 08:43:39 -05:00
|
|
|
if (!acc) return;
|
|
|
|
|
|
|
|
if (abort_now)
|
|
|
|
(percentagefunc)(NULL, -1.0);
|
|
|
|
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth++;
|
2016-11-06 10:10:30 -06:00
|
|
|
xaccAccountScrubImbalance (acc, percentagefunc);
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_account_foreach_descendant(acc,
|
2016-11-06 10:10:30 -06:00
|
|
|
(AccountCb)xaccAccountScrubImbalance, percentagefunc);
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth--;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-11-06 10:10:30 -06:00
|
|
|
xaccAccountScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2015-02-22 17:29:06 -06:00
|
|
|
GList *node, *splits;
|
2010-03-02 15:40:28 -06:00
|
|
|
const char *str;
|
2016-11-06 10:10:30 -06:00
|
|
|
const char *message = _( "Looking for imbalances in account %s: %u of %u");
|
|
|
|
gint split_count = 0, curr_split_no = 0;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!acc) return;
|
2021-11-08 20:06:29 -06:00
|
|
|
/* If it's a trading account and an imbalanced transaction is
|
|
|
|
* found the trading splits will be replaced, invalidating the
|
|
|
|
* split list in mid-traversal, see
|
|
|
|
* https://bugs.gnucash.org/show_bug.cgi?id=798346. Also the
|
|
|
|
* transactions will get scrubbed at least twice from their "real"
|
|
|
|
* accounts anyway so doing so from the trading accounts is wasted
|
|
|
|
* effort.
|
|
|
|
*/
|
|
|
|
if (xaccAccountGetType(acc) == ACCT_TYPE_TRADING)
|
|
|
|
return;
|
|
|
|
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth++;
|
2001-10-03 19:36:28 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
str = xaccAccountGetName(acc);
|
|
|
|
str = str ? str : "(null)";
|
2021-02-18 00:30:53 -06:00
|
|
|
PINFO ("Looking for imbalances in account %s\n", str);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-02-22 17:29:06 -06:00
|
|
|
splits = xaccAccountGetSplitList(acc);
|
|
|
|
split_count = g_list_length (splits);
|
|
|
|
for (node = splits; node; node = node->next)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
Split *split = node->data;
|
|
|
|
Transaction *trans = xaccSplitGetParent(split);
|
2020-08-22 18:11:17 -05:00
|
|
|
if (abort_now) break;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2015-02-22 17:29:06 -06:00
|
|
|
PINFO("Start processing split %d of %d",
|
2016-11-06 10:10:30 -06:00
|
|
|
curr_split_no + 1, split_count);
|
|
|
|
|
2020-09-06 09:52:13 -05:00
|
|
|
if (curr_split_no % 10 == 0)
|
2016-11-06 10:10:30 -06:00
|
|
|
{
|
|
|
|
char *progress_msg = g_strdup_printf (message, str, curr_split_no, split_count);
|
|
|
|
(percentagefunc)(progress_msg, (100 * curr_split_no) / split_count);
|
|
|
|
g_free (progress_msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
TransScrubOrphansFast (xaccSplitGetParent (split),
|
|
|
|
gnc_account_get_root (acc));
|
2015-02-22 17:29:06 -06:00
|
|
|
|
2013-11-10 21:09:57 -06:00
|
|
|
xaccTransScrubCurrency(trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransScrubImbalance (trans, gnc_account_get_root (acc), NULL);
|
2015-02-22 17:29:06 -06:00
|
|
|
|
|
|
|
PINFO("Finished processing split %d of %d",
|
2016-11-06 10:10:30 -06:00
|
|
|
curr_split_no + 1, split_count);
|
2015-02-22 17:29:06 -06:00
|
|
|
curr_split_no++;
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
2016-11-06 10:10:30 -06:00
|
|
|
(percentagefunc)(NULL, -1.0);
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth--;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
static Split *
|
|
|
|
get_balance_split (Transaction *trans, Account *root, Account *account,
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity *commodity)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
Split *balance_split;
|
|
|
|
gchar *accname;
|
|
|
|
|
|
|
|
if (!account ||
|
2015-10-11 23:49:53 -05:00
|
|
|
!gnc_commodity_equiv (commodity, xaccAccountGetCommodity(account)))
|
2006-03-03 18:10:44 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!root)
|
|
|
|
{
|
|
|
|
root = gnc_book_get_root_account (xaccTransGetBook (trans));
|
|
|
|
if (NULL == root)
|
|
|
|
{
|
|
|
|
/* This can't occur, things should be in books */
|
|
|
|
PERR ("Bad data corruption, no root account in book");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
accname = g_strconcat (_("Imbalance"), "-",
|
|
|
|
gnc_commodity_get_mnemonic (commodity), NULL);
|
|
|
|
account = xaccScrubUtilityGetOrMakeAccount (root, commodity,
|
2021-01-26 18:16:25 -06:00
|
|
|
accname, ACCT_TYPE_BANK,
|
|
|
|
FALSE, TRUE);
|
2010-03-02 15:40:28 -06:00
|
|
|
g_free (accname);
|
|
|
|
if (!account)
|
|
|
|
{
|
|
|
|
PERR ("Can't get balancing account");
|
|
|
|
return NULL;
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
balance_split = xaccTransFindSplitByAccount(trans, account);
|
|
|
|
|
|
|
|
/* Put split into account before setting split value */
|
|
|
|
if (!balance_split)
|
|
|
|
{
|
|
|
|
balance_split = xaccMallocSplit (qof_instance_get_book(trans));
|
2006-03-03 18:10:44 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransBeginEdit (trans);
|
|
|
|
xaccSplitSetParent(balance_split, trans);
|
|
|
|
xaccSplitSetAccount(balance_split, account);
|
|
|
|
xaccTransCommitEdit (trans);
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return balance_split;
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2021-05-04 12:11:59 -05:00
|
|
|
static gnc_commodity*
|
|
|
|
find_root_currency(void)
|
|
|
|
{
|
|
|
|
QofSession *sess = gnc_get_current_session ();
|
|
|
|
Account *root = gnc_book_get_root_account (qof_session_get_book (sess));
|
|
|
|
gnc_commodity *root_currency = xaccAccountGetCommodity (root);
|
|
|
|
|
|
|
|
/* Some older books may not have a currency set on the root
|
|
|
|
* account. In that case find the first top-level INCOME account
|
|
|
|
* and use its currency. */
|
|
|
|
if (!root_currency)
|
|
|
|
{
|
|
|
|
GList *children = gnc_account_get_children (root);
|
|
|
|
for (GList *node = children; node && !root_currency;
|
|
|
|
node = g_list_next (node))
|
|
|
|
{
|
|
|
|
Account *child = GNC_ACCOUNT (node->data);
|
|
|
|
if (xaccAccountGetType (child) == ACCT_TYPE_INCOME)
|
|
|
|
root_currency = xaccAccountGetCommodity (child);
|
|
|
|
}
|
2021-06-12 17:21:50 -05:00
|
|
|
g_list_free (children);
|
2021-05-04 12:11:59 -05:00
|
|
|
}
|
|
|
|
return root_currency;
|
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Get the trading split for a given commodity, creating it (and the
|
2021-05-04 12:11:59 -05:00
|
|
|
necessary parent accounts) if it doesn't exist. */
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
static Split *
|
2021-05-04 12:11:59 -05:00
|
|
|
get_trading_split (Transaction *trans, Account *base,
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
gnc_commodity *commodity)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
Split *balance_split;
|
|
|
|
Account *trading_account;
|
|
|
|
Account *ns_account;
|
|
|
|
Account *account;
|
2021-05-04 12:11:59 -05:00
|
|
|
Account* root = gnc_book_get_root_account (xaccTransGetBook (trans));
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
trading_account = xaccScrubUtilityGetOrMakeAccount (root,
|
2021-05-04 12:11:59 -05:00
|
|
|
NULL,
|
2015-10-11 23:49:53 -05:00
|
|
|
_("Trading"),
|
2021-01-26 18:16:25 -06:00
|
|
|
ACCT_TYPE_TRADING,
|
|
|
|
TRUE, FALSE);
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trading_account)
|
|
|
|
{
|
|
|
|
PERR ("Can't get trading account");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ns_account = xaccScrubUtilityGetOrMakeAccount (trading_account,
|
2021-05-04 12:11:59 -05:00
|
|
|
NULL,
|
2015-10-11 23:49:53 -05:00
|
|
|
gnc_commodity_get_namespace(commodity),
|
2021-01-26 18:16:25 -06:00
|
|
|
ACCT_TYPE_TRADING,
|
|
|
|
TRUE, TRUE);
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!ns_account)
|
|
|
|
{
|
|
|
|
PERR ("Can't get namespace account");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
account = xaccScrubUtilityGetOrMakeAccount (ns_account, commodity,
|
2015-10-11 23:49:53 -05:00
|
|
|
gnc_commodity_get_mnemonic(commodity),
|
2021-01-26 18:16:25 -06:00
|
|
|
ACCT_TYPE_TRADING,
|
|
|
|
FALSE, FALSE);
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!account)
|
|
|
|
{
|
|
|
|
PERR ("Can't get commodity account");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
balance_split = xaccTransFindSplitByAccount(trans, account);
|
|
|
|
|
|
|
|
/* Put split into account before setting split value */
|
|
|
|
if (!balance_split)
|
|
|
|
{
|
|
|
|
balance_split = xaccMallocSplit (qof_instance_get_book(trans));
|
|
|
|
|
|
|
|
xaccTransBeginEdit (trans);
|
|
|
|
xaccSplitSetParent(balance_split, trans);
|
|
|
|
xaccSplitSetAccount(balance_split, account);
|
|
|
|
xaccTransCommitEdit (trans);
|
|
|
|
}
|
|
|
|
|
|
|
|
return balance_split;
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
static void
|
|
|
|
add_balance_split (Transaction *trans, gnc_numeric imbalance,
|
|
|
|
Account *root, Account *account)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
const gnc_commodity *commodity;
|
|
|
|
gnc_numeric old_value, new_value;
|
|
|
|
Split *balance_split;
|
|
|
|
gnc_commodity *currency = xaccTransGetCurrency (trans);
|
|
|
|
|
|
|
|
balance_split = get_balance_split(trans, root, account, currency);
|
|
|
|
if (!balance_split)
|
|
|
|
{
|
|
|
|
/* Error already logged */
|
|
|
|
LEAVE("");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
account = xaccSplitGetAccount(balance_split);
|
|
|
|
|
|
|
|
xaccTransBeginEdit (trans);
|
|
|
|
|
|
|
|
old_value = xaccSplitGetValue (balance_split);
|
|
|
|
|
|
|
|
/* Note: We have to round for the commodity's fraction, NOT any
|
2015-10-11 23:49:53 -05:00
|
|
|
* already existing denominator (bug #104343), because either one
|
|
|
|
* of the denominators might already be reduced. */
|
2010-03-02 15:40:28 -06:00
|
|
|
new_value = gnc_numeric_sub (old_value, imbalance,
|
|
|
|
gnc_commodity_get_fraction(currency),
|
2010-10-23 05:38:48 -05:00
|
|
|
GNC_HOW_RND_ROUND_HALF_UP);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
xaccSplitSetValue (balance_split, new_value);
|
|
|
|
|
|
|
|
commodity = xaccAccountGetCommodity (account);
|
|
|
|
if (gnc_commodity_equiv (currency, commodity))
|
|
|
|
{
|
|
|
|
xaccSplitSetAmount (balance_split, new_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
xaccSplitScrub (balance_split);
|
|
|
|
xaccTransCommitEdit (trans);
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
/* Balance a transaction without trading accounts. */
|
|
|
|
static void
|
|
|
|
gnc_transaction_balance_no_trading (Transaction *trans, Account *root,
|
|
|
|
Account *account)
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
{
|
2015-10-11 23:49:53 -05:00
|
|
|
gnc_numeric imbalance = xaccTransGetImbalanceValue (trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
/* Make the value sum to zero */
|
|
|
|
if (! gnc_numeric_zero_p (imbalance))
|
2014-08-23 09:02:11 -05:00
|
|
|
{
|
2015-10-11 23:49:53 -05:00
|
|
|
PINFO ("Value unbalanced transaction");
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
add_balance_split (trans, imbalance, root, account);
|
|
|
|
}
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static gnc_numeric
|
|
|
|
gnc_transaction_get_commodity_imbalance (Transaction *trans,
|
|
|
|
gnc_commodity *commodity)
|
|
|
|
{
|
|
|
|
/* Find the value imbalance in this commodity */
|
|
|
|
gnc_numeric val_imbalance = gnc_numeric_zero();
|
|
|
|
GList *splits = NULL;
|
|
|
|
for (splits = trans->splits; splits; splits = splits->next)
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
{
|
2015-10-11 23:49:53 -05:00
|
|
|
Split *split = splits->data;
|
|
|
|
gnc_commodity *split_commodity =
|
|
|
|
xaccAccountGetCommodity(xaccSplitGetAccount(split));
|
|
|
|
if (xaccTransStillHasSplit (trans, split) &&
|
|
|
|
gnc_commodity_equal (commodity, split_commodity))
|
|
|
|
val_imbalance = gnc_numeric_add (val_imbalance,
|
|
|
|
xaccSplitGetValue (split),
|
|
|
|
GNC_DENOM_AUTO,
|
|
|
|
GNC_HOW_DENOM_EXACT);
|
|
|
|
}
|
|
|
|
return val_imbalance;
|
|
|
|
}
|
|
|
|
|
2021-05-11 16:42:21 -05:00
|
|
|
/* GFunc wrapper for xaccSplitDestroy */
|
|
|
|
static void
|
2021-09-09 18:02:00 -05:00
|
|
|
destroy_split (void* ptr)
|
2021-05-11 16:42:21 -05:00
|
|
|
{
|
|
|
|
Split *split = GNC_SPLIT (ptr);
|
|
|
|
if (split)
|
|
|
|
xaccSplitDestroy (split);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Balancing transactions with trading accounts works best when
|
|
|
|
* starting with no trading splits.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
xaccTransClearTradingSplits (Transaction *trans)
|
|
|
|
{
|
|
|
|
GList *trading_splits = NULL;
|
|
|
|
|
|
|
|
for (GList* node = trans->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
Split* split = GNC_SPLIT(node->data);
|
|
|
|
Account* acc = NULL;
|
|
|
|
if (!split)
|
|
|
|
continue;
|
|
|
|
acc = xaccSplitGetAccount(split);
|
|
|
|
if (acc && xaccAccountGetType(acc) == ACCT_TYPE_TRADING)
|
|
|
|
trading_splits = g_list_prepend (trading_splits, node->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!trading_splits)
|
|
|
|
return;
|
|
|
|
|
|
|
|
xaccTransBeginEdit (trans);
|
2021-09-09 18:02:00 -05:00
|
|
|
/* destroy_splits doesn't actually free the splits but this gets
|
Fix various typos
Found via `codespell -q 3 -S *.po,./po,*.min.js,./ChangeLog*,./NEWS,./borrowed,./doc/README*,./AUTHORS,./libgnucash/tax/us/txf-de*,./data/accounts -L ans,ba,cas,dragable,gae,iff,iif,mut,nd,numer,parm,parms,startd,stoll`
2022-04-01 08:02:10 -05:00
|
|
|
* the list itself freed.
|
2021-09-09 18:02:00 -05:00
|
|
|
*/
|
|
|
|
g_list_free_full (trading_splits, destroy_split);
|
2021-05-11 16:42:21 -05:00
|
|
|
xaccTransCommitEdit (trans);
|
|
|
|
}
|
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
static void
|
|
|
|
gnc_transaction_balance_trading (Transaction *trans, Account *root)
|
|
|
|
{
|
|
|
|
MonetaryList *imbal_list;
|
|
|
|
MonetaryList *imbalance_commod;
|
|
|
|
Split *balance_split = NULL;
|
|
|
|
|
|
|
|
/* If the transaction is balanced, nothing more to do */
|
|
|
|
imbal_list = xaccTransGetImbalance (trans);
|
|
|
|
if (!imbal_list)
|
|
|
|
{
|
|
|
|
LEAVE("transaction is balanced");
|
|
|
|
return;
|
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
PINFO ("Currency unbalanced transaction");
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
for (imbalance_commod = imbal_list; imbalance_commod;
|
|
|
|
imbalance_commod = imbalance_commod->next)
|
|
|
|
{
|
|
|
|
gnc_monetary *imbal_mon = imbalance_commod->data;
|
|
|
|
gnc_commodity *commodity;
|
|
|
|
gnc_numeric old_amount, new_amount;
|
|
|
|
const gnc_commodity *txn_curr = xaccTransGetCurrency (trans);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
commodity = gnc_monetary_commodity (*imbal_mon);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
balance_split = get_trading_split(trans, root, commodity);
|
|
|
|
if (!balance_split)
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
{
|
2015-10-11 23:49:53 -05:00
|
|
|
/* Error already logged */
|
|
|
|
gnc_monetary_list_free(imbal_list);
|
|
|
|
LEAVE("");
|
|
|
|
return;
|
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
xaccTransBeginEdit (trans);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
old_amount = xaccSplitGetAmount (balance_split);
|
|
|
|
new_amount = gnc_numeric_sub (old_amount, gnc_monetary_value(*imbal_mon),
|
|
|
|
gnc_commodity_get_fraction(commodity),
|
|
|
|
GNC_HOW_RND_ROUND_HALF_UP);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
xaccSplitSetAmount (balance_split, new_amount);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
if (gnc_commodity_equal (txn_curr, commodity))
|
|
|
|
{
|
|
|
|
/* Imbalance commodity is the transaction currency, value in the
|
|
|
|
split must be the same as the amount */
|
|
|
|
xaccSplitSetValue (balance_split, new_amount);
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
2015-10-11 23:49:53 -05:00
|
|
|
else
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2018-11-28 00:41:45 -06:00
|
|
|
gnc_numeric val_imbalance = gnc_transaction_get_commodity_imbalance (trans, commodity);
|
|
|
|
|
|
|
|
gnc_numeric old_value = xaccSplitGetValue (balance_split);
|
|
|
|
gnc_numeric new_value = gnc_numeric_sub (old_value, val_imbalance,
|
2015-10-11 23:49:53 -05:00
|
|
|
gnc_commodity_get_fraction(txn_curr),
|
|
|
|
GNC_HOW_RND_ROUND_HALF_UP);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
xaccSplitSetValue (balance_split, new_value);
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
xaccSplitScrub (balance_split);
|
|
|
|
xaccTransCommitEdit (trans);
|
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
gnc_monetary_list_free(imbal_list);
|
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
/** Balance the transaction by adding more trading splits. This shouldn't
|
|
|
|
* ordinarily be necessary.
|
|
|
|
* @param trans the transaction to balance
|
|
|
|
* @param root the root account
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
gnc_transaction_balance_trading_more_splits (Transaction *trans, Account *root)
|
|
|
|
{
|
|
|
|
/* Copy the split list so we don't see the splits we're adding */
|
|
|
|
GList *splits_dup = g_list_copy(trans->splits), *splits = NULL;
|
|
|
|
const gnc_commodity *txn_curr = xaccTransGetCurrency (trans);
|
|
|
|
for (splits = splits_dup; splits; splits = splits->next)
|
|
|
|
{
|
|
|
|
Split *split = splits->data;
|
|
|
|
if (! xaccTransStillHasSplit(trans, split)) continue;
|
|
|
|
if (!gnc_numeric_zero_p(xaccSplitGetValue(split)) &&
|
|
|
|
gnc_numeric_zero_p(xaccSplitGetAmount(split)))
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
gnc_commodity *commodity;
|
2015-10-11 23:49:53 -05:00
|
|
|
gnc_numeric old_value, new_value;
|
|
|
|
Split *balance_split;
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
commodity = xaccAccountGetCommodity(xaccSplitGetAccount(split));
|
|
|
|
if (!commodity)
|
|
|
|
{
|
|
|
|
PERR("Split has no commodity");
|
|
|
|
continue;
|
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
balance_split = get_trading_split(trans, root, commodity);
|
|
|
|
if (!balance_split)
|
|
|
|
{
|
|
|
|
/* Error already logged */
|
|
|
|
LEAVE("");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
xaccTransBeginEdit (trans);
|
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
old_value = xaccSplitGetValue (balance_split);
|
|
|
|
new_value = gnc_numeric_sub (old_value, xaccSplitGetValue(split),
|
|
|
|
gnc_commodity_get_fraction(txn_curr),
|
|
|
|
GNC_HOW_RND_ROUND_HALF_UP);
|
|
|
|
xaccSplitSetValue (balance_split, new_value);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
/* Don't change the balance split's amount since the amount
|
|
|
|
is zero in the split we're working on */
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
xaccSplitScrub (balance_split);
|
|
|
|
xaccTransCommitEdit (trans);
|
|
|
|
}
|
2015-10-11 23:49:53 -05:00
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
g_list_free(splits_dup);
|
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
/** Correct transaction imbalances.
|
|
|
|
* @param trans The Transaction
|
|
|
|
* @param root The (hidden) root account, for the book default currency.
|
|
|
|
* @param account The account whose currency in which to balance.
|
|
|
|
*/
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
void
|
|
|
|
xaccTransScrubImbalance (Transaction *trans, Account *root,
|
|
|
|
Account *account)
|
|
|
|
{
|
|
|
|
gnc_numeric imbalance;
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2015-10-11 23:49:53 -05:00
|
|
|
if (!trans) return;
|
|
|
|
|
|
|
|
ENTER ("()");
|
|
|
|
|
2021-10-14 19:21:13 -05:00
|
|
|
/* Must look for orphan splits even if there is no imbalance. */
|
2015-10-11 23:49:53 -05:00
|
|
|
xaccTransScrubSplits (trans);
|
|
|
|
|
|
|
|
/* Return immediately if things are balanced. */
|
|
|
|
if (xaccTransIsBalanced (trans))
|
|
|
|
{
|
|
|
|
LEAVE ("transaction is balanced");
|
|
|
|
return;
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
2015-10-11 23:49:53 -05:00
|
|
|
|
|
|
|
if (! xaccTransUseTradingAccounts (trans))
|
|
|
|
{
|
|
|
|
gnc_transaction_balance_no_trading (trans, root, account);
|
2021-10-14 19:21:13 -05:00
|
|
|
LEAVE ("transaction balanced, no managed trading accounts");
|
2015-10-11 23:49:53 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-10-14 19:21:13 -05:00
|
|
|
xaccTransClearTradingSplits (trans);
|
2021-05-11 16:42:21 -05:00
|
|
|
imbalance = xaccTransGetImbalanceValue (trans);
|
2015-10-11 23:49:53 -05:00
|
|
|
if (! gnc_numeric_zero_p (imbalance))
|
|
|
|
{
|
|
|
|
PINFO ("Value unbalanced transaction");
|
|
|
|
|
|
|
|
add_balance_split (trans, imbalance, root, account);
|
|
|
|
}
|
|
|
|
|
|
|
|
gnc_transaction_balance_trading (trans, root);
|
|
|
|
if (gnc_numeric_zero_p(xaccTransGetImbalanceValue(trans)))
|
|
|
|
{
|
|
|
|
LEAVE ("()");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* If the transaction is still not balanced, it's probably because there
|
|
|
|
are splits with zero amount and non-zero value. These are usually
|
|
|
|
realized gain/loss splits. Add a reversing split for each of them to
|
|
|
|
balance the value. */
|
|
|
|
|
|
|
|
gnc_transaction_balance_trading_more_splits (trans, root);
|
|
|
|
if (!gnc_numeric_zero_p(xaccTransGetImbalanceValue(trans)))
|
|
|
|
PERR("Balancing currencies unbalanced value");
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2003-09-12 08:17:26 -05:00
|
|
|
/* ================================================================ */
|
|
|
|
/* The xaccTransFindCommonCurrency () method returns
|
|
|
|
* a gnc_commodity indicating a currency denomination that all
|
|
|
|
* of the splits in this transaction have in common, using the
|
2010-03-02 15:40:28 -06:00
|
|
|
* old/obsolete currency/security fields of the split accounts.
|
2003-09-12 08:17:26 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
static gnc_commodity *
|
|
|
|
FindCommonExclSCurrency (SplitList *splits,
|
|
|
|
gnc_commodity * ra, gnc_commodity * rb,
|
|
|
|
Split *excl_split)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *node;
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!splits) return NULL;
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
for (node = splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
Split *s = node->data;
|
|
|
|
gnc_commodity * sa, * sb;
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (s == excl_split) continue;
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_return_val_if_fail (s->acc, NULL);
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
sa = DxaccAccountGetCurrency (s->acc);
|
|
|
|
sb = xaccAccountGetCommodity (s->acc);
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
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;
|
|
|
|
}
|
2010-11-02 16:14:38 -05:00
|
|
|
else if (!ra && rb)
|
|
|
|
{
|
|
|
|
int aa = !gnc_commodity_equiv(rb, sa);
|
|
|
|
int ab = !gnc_commodity_equiv(rb, sb);
|
|
|
|
ra = ( aa && ab ) ? NULL : rb;
|
|
|
|
}
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if ((!ra) && (!rb)) return NULL;
|
2003-09-12 08:17:26 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return (ra);
|
2003-09-12 08:17:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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
|
2010-03-02 15:40:28 -06:00
|
|
|
* common currency.
|
2003-09-12 08:17:26 -05:00
|
|
|
*/
|
|
|
|
static gnc_commodity *
|
|
|
|
FindCommonCurrency (GList *splits, gnc_commodity * ra, gnc_commodity * rb)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
return FindCommonExclSCurrency(splits, ra, rb, NULL);
|
2003-09-12 08:17:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static gnc_commodity *
|
|
|
|
xaccTransFindOldCommonCurrency (Transaction *trans, QofBook *book)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity *ra, *rb, *retval;
|
|
|
|
Split *split;
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans) return NULL;
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (trans->splits == NULL) return NULL;
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_return_val_if_fail (book, NULL);
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
split = trans->splits->data;
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!split || NULL == split->acc) return NULL;
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ra = DxaccAccountGetCurrency (split->acc);
|
|
|
|
rb = xaccAccountGetCommodity (split->acc);
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
retval = FindCommonCurrency (trans->splits, ra, rb);
|
2003-09-12 08:17:26 -05:00
|
|
|
|
2013-11-10 21:09:57 -06:00
|
|
|
if (retval && !gnc_commodity_is_currency(retval))
|
|
|
|
retval = NULL;
|
2015-10-11 23:49:53 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return retval;
|
2003-09-12 08:17:26 -05:00
|
|
|
}
|
|
|
|
|
2010-11-02 16:14:38 -05:00
|
|
|
/* Test the currency of the splits and find the most common and return
|
|
|
|
* it, or NULL if there is no currency more common than the
|
|
|
|
* others -- or none at all.
|
|
|
|
*/
|
2010-12-04 15:09:57 -06:00
|
|
|
typedef struct
|
|
|
|
{
|
2010-11-02 16:14:38 -05:00
|
|
|
gnc_commodity *commodity;
|
|
|
|
unsigned int count;
|
|
|
|
} CommodityCount;
|
|
|
|
|
|
|
|
static gint
|
|
|
|
commodity_equal (gconstpointer a, gconstpointer b)
|
|
|
|
{
|
|
|
|
CommodityCount *cc = (CommodityCount*)a;
|
|
|
|
gnc_commodity *com = (gnc_commodity*)b;
|
2010-12-04 15:09:57 -06:00
|
|
|
if ( cc == NULL || cc->commodity == NULL ||
|
2015-10-11 23:49:53 -05:00
|
|
|
!GNC_IS_COMMODITY( cc->commodity ) ) return -1;
|
2010-11-02 16:14:38 -05:00
|
|
|
if ( com == NULL || !GNC_IS_COMMODITY( com ) ) return 1;
|
|
|
|
if ( gnc_commodity_equal(cc->commodity, com) )
|
2010-12-04 15:09:57 -06:00
|
|
|
return 0;
|
2010-11-02 16:14:38 -05:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
commodity_compare( gconstpointer a, gconstpointer b)
|
|
|
|
{
|
|
|
|
CommodityCount *ca = (CommodityCount*)a, *cb = (CommodityCount*)b;
|
|
|
|
if (ca == NULL || ca->commodity == NULL ||
|
2015-10-11 23:49:53 -05:00
|
|
|
!GNC_IS_COMMODITY( ca->commodity ) )
|
2010-11-02 16:14:38 -05:00
|
|
|
{
|
2010-12-04 15:09:57 -06:00
|
|
|
if (cb == NULL || cb->commodity == NULL ||
|
2015-10-11 23:49:53 -05:00
|
|
|
!GNC_IS_COMMODITY( cb->commodity ) )
|
2010-12-04 15:09:57 -06:00
|
|
|
return 0;
|
|
|
|
return -1;
|
2010-11-02 16:14:38 -05:00
|
|
|
}
|
|
|
|
if (cb == NULL || cb->commodity == NULL ||
|
2015-10-11 23:49:53 -05:00
|
|
|
!GNC_IS_COMMODITY( cb->commodity ) )
|
2010-12-04 15:09:57 -06:00
|
|
|
return 1;
|
2010-11-02 16:14:38 -05:00
|
|
|
if (ca->count == cb->count)
|
2010-12-04 15:09:57 -06:00
|
|
|
return 0;
|
2010-11-02 16:14:38 -05:00
|
|
|
return ca->count > cb->count ? 1 : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Find the commodities in the account of each of the splits of a
|
|
|
|
* transaction, and rank them by how many splits in which they
|
|
|
|
* occur. Commodities which are currencies count more than those which
|
|
|
|
* aren't, because for simple buy and sell transactions it makes
|
|
|
|
* slightly more sense for the transaction commodity to be the
|
|
|
|
* currency -- to the extent that it makes sense for a transaction to
|
2010-12-04 15:09:57 -06:00
|
|
|
* have a currency at all. jralls, 2010-11-02 */
|
2010-11-02 16:14:38 -05:00
|
|
|
|
|
|
|
static gnc_commodity *
|
|
|
|
xaccTransFindCommonCurrency (Transaction *trans, QofBook *book)
|
|
|
|
{
|
2012-05-26 18:47:34 -05:00
|
|
|
gnc_commodity *com_scratch;
|
2010-11-02 16:14:38 -05:00
|
|
|
GList *node = NULL;
|
|
|
|
GSList *comlist = NULL, *found = NULL;
|
|
|
|
|
|
|
|
if (!trans) return NULL;
|
|
|
|
|
|
|
|
if (trans->splits == NULL) return NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (book, NULL);
|
|
|
|
|
2013-11-10 21:09:57 -06:00
|
|
|
/* Find the most commonly used currency among the splits. If a given split
|
2015-10-11 23:49:53 -05:00
|
|
|
is in a non-currency commodity, then look for an ancestor account in a
|
2013-11-10 21:09:57 -06:00
|
|
|
currency, but prefer currencies used directly in splits. Ignore trading
|
|
|
|
account splits in this whole process, they don't add any value to this algorithm. */
|
2010-11-02 16:14:38 -05:00
|
|
|
for (node = trans->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
Split *s = node->data;
|
2013-11-10 21:09:57 -06:00
|
|
|
unsigned int curr_weight;
|
2015-10-11 23:49:53 -05:00
|
|
|
|
2010-12-04 15:09:57 -06:00
|
|
|
if (s == NULL || s->acc == NULL) continue;
|
2013-11-10 21:09:57 -06:00
|
|
|
if (xaccAccountGetType(s->acc) == ACCT_TYPE_TRADING) continue;
|
2010-12-04 15:09:57 -06:00
|
|
|
com_scratch = xaccAccountGetCommodity(s->acc);
|
2013-11-10 21:09:57 -06:00
|
|
|
if (com_scratch && gnc_commodity_is_currency(com_scratch))
|
|
|
|
{
|
|
|
|
curr_weight = 3;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
com_scratch = gnc_account_get_currency_or_parent(s->acc);
|
|
|
|
if (com_scratch == NULL) continue;
|
|
|
|
curr_weight = 1;
|
|
|
|
}
|
2010-12-04 15:09:57 -06:00
|
|
|
if ( comlist )
|
|
|
|
{
|
|
|
|
found = g_slist_find_custom(comlist, com_scratch, commodity_equal);
|
|
|
|
}
|
|
|
|
if (comlist == NULL || found == NULL)
|
|
|
|
{
|
|
|
|
CommodityCount *count = g_slice_new0(CommodityCount);
|
|
|
|
count->commodity = com_scratch;
|
2013-11-10 21:09:57 -06:00
|
|
|
count->count = curr_weight;
|
2010-12-04 15:09:57 -06:00
|
|
|
comlist = g_slist_append(comlist, count);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CommodityCount *count = (CommodityCount*)(found->data);
|
2013-11-10 21:09:57 -06:00
|
|
|
count->count += curr_weight;
|
2010-12-04 15:09:57 -06:00
|
|
|
}
|
2010-11-02 16:14:38 -05:00
|
|
|
}
|
|
|
|
found = g_slist_sort( comlist, commodity_compare);
|
|
|
|
|
2013-06-30 15:38:14 -05:00
|
|
|
if ( found && found->data && (((CommodityCount*)(found->data))->commodity != NULL))
|
2010-11-02 16:14:38 -05:00
|
|
|
{
|
2010-12-04 15:09:57 -06:00
|
|
|
return ((CommodityCount*)(found->data))->commodity;
|
2010-11-02 16:14:38 -05:00
|
|
|
}
|
2010-12-04 15:09:57 -06:00
|
|
|
/* We didn't find a currency in the current account structure, so try
|
|
|
|
* an old one. */
|
2010-11-02 16:14:38 -05:00
|
|
|
return xaccTransFindOldCommonCurrency( trans, book );
|
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/* ================================================================ */
|
|
|
|
|
|
|
|
void
|
2003-03-30 21:25:19 -06:00
|
|
|
xaccTransScrubCurrency (Transaction *trans)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
SplitList *node;
|
|
|
|
gnc_commodity *currency;
|
|
|
|
|
|
|
|
if (!trans) return;
|
|
|
|
|
|
|
|
/* If there are any orphaned splits in a transaction, then the
|
|
|
|
* this routine will fail. Therefore, we want to make sure that
|
|
|
|
* there are no orphans (splits without parent account).
|
|
|
|
*/
|
|
|
|
xaccTransScrubOrphans (trans);
|
|
|
|
|
|
|
|
currency = xaccTransGetCurrency (trans);
|
2013-11-10 21:09:57 -06:00
|
|
|
if (currency && gnc_commodity_is_currency(currency)) return;
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2010-11-02 16:14:38 -05:00
|
|
|
currency = xaccTransFindCommonCurrency (trans, qof_instance_get_book(trans));
|
2010-03-02 15:40:28 -06:00
|
|
|
if (currency)
|
2003-04-03 09:18:25 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransBeginEdit (trans);
|
|
|
|
xaccTransSetCurrency (trans, currency);
|
|
|
|
xaccTransCommitEdit (trans);
|
2003-04-03 09:18:25 -06:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (NULL == trans->splits)
|
2003-04-03 09:18:25 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
PWARN ("Transaction \"%s\" has no splits in it!", trans->description);
|
2003-04-03 09:18:25 -06:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
SplitList *node;
|
2011-07-17 12:35:30 -05:00
|
|
|
char guid_str[GUID_ENCODING_LENGTH + 1];
|
2010-03-02 15:40:28 -06:00
|
|
|
guid_to_string_buff(xaccTransGetGUID(trans), guid_str);
|
2013-12-08 20:02:41 -06:00
|
|
|
PWARN ("no common transaction currency found for trans=\"%s\" (%s);",
|
2010-03-02 15:40:28 -06:00
|
|
|
trans->description, guid_str);
|
|
|
|
|
|
|
|
for (node = trans->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
Split *split = node->data;
|
|
|
|
if (NULL == split->acc)
|
|
|
|
{
|
|
|
|
PWARN (" split=\"%s\" is not in any account!", split->memo);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-12-22 12:07:55 -06:00
|
|
|
gnc_commodity *currency = xaccAccountGetCommodity(split->acc);
|
2013-12-08 20:02:41 -06:00
|
|
|
PWARN ("setting to split=\"%s\" account=\"%s\" commodity=\"%s\"",
|
2010-03-02 15:40:28 -06:00
|
|
|
split->memo, xaccAccountGetName(split->acc),
|
2013-12-08 20:02:41 -06:00
|
|
|
gnc_commodity_get_mnemonic(currency));
|
|
|
|
|
2018-12-22 12:07:55 -06:00
|
|
|
xaccTransBeginEdit (trans);
|
|
|
|
xaccTransSetCurrency (trans, currency);
|
|
|
|
xaccTransCommitEdit (trans);
|
|
|
|
return;
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
|
|
|
}
|
2003-04-03 09:18:25 -06:00
|
|
|
}
|
2013-11-10 21:09:57 -06:00
|
|
|
return;
|
2003-04-03 09:18:25 -06:00
|
|
|
}
|
2003-04-04 23:38:12 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
for (node = trans->splits; node; node = node->next)
|
2003-04-03 09:18:25 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
Split *sp = node->data;
|
|
|
|
|
|
|
|
if (!gnc_numeric_equal(xaccSplitGetAmount (sp),
|
|
|
|
xaccSplitGetValue (sp)))
|
|
|
|
{
|
|
|
|
gnc_commodity *acc_currency;
|
|
|
|
|
|
|
|
acc_currency = sp->acc ? xaccAccountGetCommodity(sp->acc) : NULL;
|
|
|
|
if (acc_currency == currency)
|
|
|
|
{
|
|
|
|
/* This Split needs fixing: The transaction-currency equals
|
|
|
|
* the account-currency/commodity, but the amount/values are
|
|
|
|
* inequal i.e. they still correspond to the security
|
|
|
|
* (amount) and the currency (value). In the new model, the
|
|
|
|
* value is the amount in the account-commodity -- so it
|
|
|
|
* needs to be set to equal the amount (since the
|
|
|
|
* account-currency doesn't exist anymore).
|
|
|
|
*
|
|
|
|
* Note: Nevertheless we lose some information here. Namely,
|
|
|
|
* the information that the 'amount' in 'account-old-security'
|
|
|
|
* was worth 'value' in 'account-old-currency'. Maybe it would
|
|
|
|
* be better to store that information in the price database?
|
|
|
|
* But then, for old currency transactions there is still the
|
|
|
|
* 'other' transaction, which is going to keep that
|
|
|
|
* information. So I don't bother with that here. -- cstim,
|
|
|
|
* 2002/11/20. */
|
|
|
|
|
|
|
|
PWARN ("Adjusted split with mismatched values, desc=\"%s\" memo=\"%s\""
|
|
|
|
" old amount %s %s, new amount %s",
|
|
|
|
trans->description, sp->memo,
|
|
|
|
gnc_num_dbg_to_string (xaccSplitGetAmount(sp)),
|
|
|
|
gnc_commodity_get_mnemonic (currency),
|
|
|
|
gnc_num_dbg_to_string (xaccSplitGetValue(sp)));
|
|
|
|
xaccTransBeginEdit (trans);
|
2013-11-10 21:09:57 -06:00
|
|
|
xaccSplitSetAmount (sp, xaccSplitGetValue(sp));
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransCommitEdit (trans);
|
|
|
|
}
|
|
|
|
/*else
|
2015-10-11 23:49:53 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
PINFO ("Ok: Split '%s' Amount %s %s, value %s %s",
|
|
|
|
xaccSplitGetMemo (sp),
|
|
|
|
gnc_num_dbg_to_string (amount),
|
|
|
|
gnc_commodity_get_mnemonic (currency),
|
|
|
|
gnc_num_dbg_to_string (value),
|
|
|
|
gnc_commodity_get_mnemonic (acc_currency));
|
2015-10-11 23:49:53 -05:00
|
|
|
}*/
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
2002-11-19 16:31:47 -06:00
|
|
|
}
|
2010-11-02 16:14:38 -05:00
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ================================================================ */
|
|
|
|
|
|
|
|
void
|
2003-03-30 21:25:19 -06:00
|
|
|
xaccAccountScrubCommodity (Account *account)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity *commodity;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!account) return;
|
|
|
|
if (xaccAccountGetType(account) == ACCT_TYPE_ROOT) return;
|
2001-10-03 05:07:45 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
commodity = xaccAccountGetCommodity (account);
|
|
|
|
if (commodity) return;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Use the 'obsolete' routines to try to figure out what the
|
|
|
|
* account commodity should have been. */
|
2010-12-13 15:00:23 -06:00
|
|
|
commodity = xaccAccountGetCommodity (account);
|
2010-03-02 15:40:28 -06:00
|
|
|
if (commodity)
|
|
|
|
{
|
|
|
|
xaccAccountSetCommodity (account, commodity);
|
|
|
|
return;
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
commodity = DxaccAccountGetCurrency (account);
|
|
|
|
if (commodity)
|
|
|
|
{
|
|
|
|
xaccAccountSetCommodity (account, commodity);
|
|
|
|
return;
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
PERR ("Account \"%s\" does not have a commodity!",
|
|
|
|
xaccAccountGetName(account));
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ================================================================ */
|
|
|
|
|
2014-05-07 08:37:14 -05:00
|
|
|
/* EFFECTIVE FRIEND FUNCTION declared in qofinstance-p.h */
|
|
|
|
extern void qof_instance_set_dirty (QofInstance*);
|
|
|
|
|
2003-09-12 08:17:26 -05:00
|
|
|
static void
|
|
|
|
xaccAccountDeleteOldData (Account *account)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!account) return;
|
2011-12-18 18:47:20 -06:00
|
|
|
xaccAccountBeginEdit (account);
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (account), NULL, 1, "old-currency");
|
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (account), NULL, 1, "old-security");
|
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (account), NULL, 1, "old-currency-scu");
|
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (account), NULL, 1, "old-security-scu");
|
2011-12-18 18:47:20 -06:00
|
|
|
qof_instance_set_dirty (QOF_INSTANCE (account));
|
|
|
|
xaccAccountCommitEdit (account);
|
2003-09-12 08:17:26 -05:00
|
|
|
}
|
|
|
|
|
2003-08-16 16:13:31 -05:00
|
|
|
static int
|
2001-10-03 05:07:45 -05:00
|
|
|
scrub_trans_currency_helper (Transaction *t, gpointer data)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransScrubCurrency (t);
|
|
|
|
return 0;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2007-02-22 19:23:31 -06:00
|
|
|
static void
|
2001-10-03 05:07:45 -05:00
|
|
|
scrub_account_commodity_helper (Account *account, gpointer data)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth++;
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccAccountScrubCommodity (account);
|
|
|
|
xaccAccountDeleteOldData (account);
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth--;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-02-22 19:23:31 -06:00
|
|
|
xaccAccountTreeScrubCommodities (Account *acc)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!acc) return;
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth++;
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccAccountTreeForEachTransaction (acc, scrub_trans_currency_helper, NULL);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
scrub_account_commodity_helper (acc, NULL);
|
|
|
|
gnc_account_foreach_descendant (acc, scrub_account_commodity_helper, NULL);
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth--;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ================================================================ */
|
2003-05-10 19:45:03 -05:00
|
|
|
|
|
|
|
static gboolean
|
|
|
|
check_quote_source (gnc_commodity *com, gpointer data)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gboolean *commodity_has_quote_src = (gboolean *)data;
|
|
|
|
if (com && !gnc_commodity_is_iso(com))
|
|
|
|
*commodity_has_quote_src |= gnc_commodity_get_quote_flag(com);
|
|
|
|
return TRUE;
|
2003-05-10 19:45:03 -05:00
|
|
|
}
|
|
|
|
|
2007-02-22 19:23:31 -06:00
|
|
|
static void
|
2003-05-10 19:45:03 -05:00
|
|
|
move_quote_source (Account *account, gpointer data)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity *com;
|
|
|
|
gnc_quote_source *quote_source;
|
|
|
|
gboolean new_style = GPOINTER_TO_INT(data);
|
|
|
|
const char *source, *tz;
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
com = xaccAccountGetCommodity(account);
|
|
|
|
if (!com)
|
|
|
|
return;
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!new_style)
|
|
|
|
{
|
|
|
|
source = dxaccAccountGetPriceSrc(account);
|
|
|
|
if (!source || !*source)
|
|
|
|
return;
|
|
|
|
tz = dxaccAccountGetQuoteTZ(account);
|
|
|
|
|
|
|
|
PINFO("to %8s from %s", gnc_commodity_get_mnemonic(com),
|
|
|
|
xaccAccountGetName(account));
|
|
|
|
gnc_commodity_set_quote_flag(com, TRUE);
|
|
|
|
quote_source = gnc_quote_source_lookup_by_internal(source);
|
|
|
|
if (!quote_source)
|
|
|
|
quote_source = gnc_quote_source_add_new(source, FALSE);
|
|
|
|
gnc_commodity_set_quote_source(com, quote_source);
|
|
|
|
gnc_commodity_set_quote_tz(com, tz);
|
|
|
|
}
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
dxaccAccountSetPriceSrc(account, NULL);
|
|
|
|
dxaccAccountSetQuoteTZ(account, NULL);
|
|
|
|
return;
|
2003-05-10 19:45:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2007-02-22 19:23:31 -06:00
|
|
|
xaccAccountTreeScrubQuoteSources (Account *root, gnc_commodity_table *table)
|
2003-05-10 19:45:03 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gboolean new_style = FALSE;
|
|
|
|
ENTER(" ");
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!root || !table)
|
|
|
|
{
|
|
|
|
LEAVE("Oops");
|
|
|
|
return;
|
|
|
|
}
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth++;
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_table_foreach_commodity (table, check_quote_source, &new_style);
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
move_quote_source(root, GINT_TO_POINTER(new_style));
|
|
|
|
gnc_account_foreach_descendant (root, move_quote_source,
|
|
|
|
GINT_TO_POINTER(new_style));
|
|
|
|
LEAVE("Migration done");
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth--;
|
2003-05-10 19:45:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ================================================================ */
|
2006-04-15 13:50:59 -05:00
|
|
|
|
|
|
|
void
|
|
|
|
xaccAccountScrubKvp (Account *account)
|
|
|
|
{
|
2015-06-04 15:32:15 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2010-03-02 15:40:28 -06:00
|
|
|
gchar *str2;
|
|
|
|
|
|
|
|
if (!account) return;
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth++;
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (account), &v, 1, "notes");
|
2015-06-04 15:32:15 -05:00
|
|
|
if (G_VALUE_HOLDS_STRING (&v))
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2015-06-04 15:32:15 -05:00
|
|
|
str2 = g_strstrip(g_value_dup_string(&v));
|
2010-03-02 15:40:28 -06:00
|
|
|
if (strlen(str2) == 0)
|
2017-11-09 15:33:58 -06:00
|
|
|
qof_instance_slot_delete (QOF_INSTANCE (account), "notes");
|
2010-03-02 15:40:28 -06:00
|
|
|
g_free(str2);
|
|
|
|
}
|
|
|
|
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (account), &v, 1, "placeholder");
|
2015-06-04 15:32:15 -05:00
|
|
|
if ((G_VALUE_HOLDS_STRING (&v) &&
|
|
|
|
strcmp(g_value_get_string (&v), "false") == 0) ||
|
|
|
|
(G_VALUE_HOLDS_BOOLEAN (&v) && ! g_value_get_boolean (&v)))
|
2017-11-09 15:33:58 -06:00
|
|
|
qof_instance_slot_delete (QOF_INSTANCE (account), "placeholder");
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2021-06-01 09:45:33 -05:00
|
|
|
g_value_unset (&v);
|
2017-11-09 15:33:58 -06:00
|
|
|
qof_instance_slot_delete_if_empty (QOF_INSTANCE (account), "hbci");
|
2020-08-22 18:11:17 -05:00
|
|
|
scrub_depth--;
|
2006-04-15 13:50:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ================================================================ */
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2018-12-22 12:07:55 -06:00
|
|
|
void
|
|
|
|
xaccAccountScrubColorNotSet (QofBook *book)
|
|
|
|
{
|
|
|
|
GValue value_s = G_VALUE_INIT;
|
2021-06-01 09:45:33 -05:00
|
|
|
gboolean already_scrubbed;
|
2018-12-22 12:07:55 -06:00
|
|
|
|
|
|
|
// get the run-once value
|
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (book), &value_s, 1, "remove-color-not-set-slots");
|
|
|
|
|
2021-06-01 09:45:33 -05:00
|
|
|
already_scrubbed = (G_VALUE_HOLDS_STRING (&value_s) &&
|
|
|
|
!g_strcmp0 (g_value_get_string (&value_s), "true"));
|
|
|
|
g_value_unset (&value_s);
|
|
|
|
|
|
|
|
if (already_scrubbed)
|
2018-12-22 12:07:55 -06:00
|
|
|
return;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GValue value_b = G_VALUE_INIT;
|
|
|
|
Account *root = gnc_book_get_root_account (book);
|
|
|
|
GList *accts = gnc_account_get_descendants_sorted (root);
|
|
|
|
GList *ptr;
|
|
|
|
|
|
|
|
for (ptr = accts; ptr; ptr = g_list_next (ptr))
|
|
|
|
{
|
|
|
|
const gchar *color = xaccAccountGetColor (ptr->data);
|
|
|
|
|
|
|
|
if (g_strcmp0 (color, "Not Set") == 0)
|
|
|
|
xaccAccountSetColor (ptr->data, "");
|
|
|
|
}
|
|
|
|
g_list_free (accts);
|
|
|
|
|
|
|
|
g_value_init (&value_b, G_TYPE_BOOLEAN);
|
|
|
|
g_value_set_boolean (&value_b, TRUE);
|
|
|
|
|
|
|
|
// set the run-once value
|
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (book), &value_b, 1, "remove-color-not-set-slots");
|
2021-06-01 09:45:33 -05:00
|
|
|
g_value_unset (&value_b);
|
2018-12-22 12:07:55 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ================================================================ */
|
|
|
|
|
2021-05-04 12:11:59 -05:00
|
|
|
static Account*
|
|
|
|
construct_account (Account *root, gnc_commodity *currency, const char *accname,
|
|
|
|
GNCAccountType acctype, gboolean placeholder)
|
|
|
|
{
|
|
|
|
gnc_commodity* root_currency = find_root_currency ();
|
|
|
|
Account *acc = xaccMallocAccount(gnc_account_get_book (root));
|
|
|
|
xaccAccountBeginEdit (acc);
|
|
|
|
if (accname && *accname)
|
|
|
|
xaccAccountSetName (acc, accname);
|
|
|
|
if (currency || root_currency)
|
|
|
|
xaccAccountSetCommodity (acc, currency ? currency : root_currency);
|
|
|
|
xaccAccountSetType (acc, acctype);
|
|
|
|
xaccAccountSetPlaceholder (acc, placeholder);
|
|
|
|
|
|
|
|
/* Hang the account off the root. */
|
|
|
|
gnc_account_append_child (root, acc);
|
|
|
|
xaccAccountCommitEdit (acc);
|
|
|
|
return acc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Account*
|
|
|
|
find_root_currency_account_in_list (GList *acc_list)
|
|
|
|
{
|
|
|
|
gnc_commodity* root_currency = find_root_currency();
|
|
|
|
for (GList *node = acc_list; node; node = g_list_next (node))
|
|
|
|
{
|
|
|
|
Account *acc = GNC_ACCOUNT (node->data);
|
|
|
|
gnc_commodity *acc_commodity = NULL;
|
|
|
|
if (G_UNLIKELY (!acc)) continue;
|
|
|
|
acc_commodity = xaccAccountGetCommodity(acc);
|
|
|
|
if (gnc_commodity_equiv (acc_commodity, root_currency))
|
|
|
|
return acc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Account*
|
|
|
|
find_account_matching_name_in_list (GList *acc_list, const char* accname)
|
|
|
|
{
|
|
|
|
for (GList* node = acc_list; node; node = g_list_next(node))
|
|
|
|
{
|
|
|
|
Account *acc = GNC_ACCOUNT (node->data);
|
|
|
|
if (G_UNLIKELY (!acc)) continue;
|
2021-07-08 03:33:10 -05:00
|
|
|
if (g_strcmp0 (accname, xaccAccountGetName (acc)) == 0)
|
2021-05-04 12:11:59 -05:00
|
|
|
return acc;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2003-03-30 23:15:21 -06:00
|
|
|
Account *
|
2007-02-22 19:23:31 -06:00
|
|
|
xaccScrubUtilityGetOrMakeAccount (Account *root, gnc_commodity * currency,
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
const char *accname, GNCAccountType acctype,
|
2021-01-26 18:16:25 -06:00
|
|
|
gboolean placeholder, gboolean checkname)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2021-05-04 12:11:59 -05:00
|
|
|
GList* acc_list;
|
|
|
|
Account *acc = NULL;
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
g_return_val_if_fail (root, NULL);
|
|
|
|
|
2021-05-04 12:11:59 -05:00
|
|
|
acc_list =
|
|
|
|
gnc_account_lookup_by_type_and_commodity (root,
|
|
|
|
checkname ? accname : NULL,
|
|
|
|
acctype, currency);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2021-05-04 12:11:59 -05:00
|
|
|
if (!acc_list)
|
|
|
|
return construct_account (root, currency, accname,
|
|
|
|
acctype, placeholder);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2021-05-04 12:11:59 -05:00
|
|
|
if (g_list_next(acc_list))
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2021-05-04 12:11:59 -05:00
|
|
|
if (!currency)
|
|
|
|
acc = find_root_currency_account_in_list (acc_list);
|
|
|
|
|
|
|
|
if (!acc)
|
|
|
|
acc = find_account_matching_name_in_list (acc_list, accname);
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
|
|
|
|
2021-05-04 12:11:59 -05:00
|
|
|
if (!acc)
|
|
|
|
acc = GNC_ACCOUNT (acc_list->data);
|
|
|
|
|
|
|
|
g_list_free (acc_list);
|
2010-03-02 15:40:28 -06:00
|
|
|
return acc;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2016-07-02 18:03:55 -05:00
|
|
|
void
|
|
|
|
xaccTransScrubPostedDate (Transaction *trans)
|
|
|
|
{
|
|
|
|
time64 orig = xaccTransGetDate(trans);
|
2018-12-29 06:45:47 -06:00
|
|
|
if(orig == INT64_MAX)
|
2016-07-02 18:03:55 -05:00
|
|
|
{
|
2018-12-29 06:45:47 -06:00
|
|
|
GDate date = xaccTransGetDatePostedGDate(trans);
|
|
|
|
time64 time = gdate_to_time64(date);
|
|
|
|
if(time != INT64_MAX)
|
|
|
|
{
|
|
|
|
// xaccTransSetDatePostedSecs handles committing the change.
|
|
|
|
xaccTransSetDatePostedSecs(trans, time);
|
|
|
|
}
|
2016-07-02 18:03:55 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/* ==================== END OF FILE ==================== */
|