Add API for getting and setting the 'balance split'.

Redo Scrub using gnc_numerics.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3130 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Dave Peticolas 2000-11-07 19:51:15 +00:00
parent 0e65931103
commit c027366e7a
5 changed files with 129 additions and 50 deletions

View File

@ -32,8 +32,8 @@
* Copyright (c) 1998, 1999, 2000 Linas Vepstas
*/
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Account.h"
@ -41,6 +41,7 @@
#include "GroupP.h"
#include "Scrub.h"
#include "Transaction.h"
#include "TransactionP.h"
#include "gnc-engine-util.h"
#include "messages.h"
@ -73,9 +74,9 @@ xaccAccountScrubOrphans (Account *acc) {
GList *slp;
Transaction *trans;
Account * parent;
PINFO ("Looking for orphans in account %s \n", xaccAccountGetName(acc));
for(slp = xaccAccountGetSplitList(acc); slp; slp = slp->next) {
Split *split = (Split *) slp->data;
Split * tsplit;
@ -130,30 +131,57 @@ xaccAccountScrubImbalance (Account *acc) {
for(slp = xaccAccountGetSplitList(acc); slp; slp = slp->next) {
Split *split = (Split *) slp->data;
Transaction *trans = xaccSplitGetParent(split);
double imbalance;
imbalance = DxaccTransGetImbalance (trans);
if (!(DEQ (imbalance, 0.0))) {
Split *splat;
Account *orph;
DEBUG ("Found imbalance of %g\n", imbalance);
/* OK, we found an imbalanced trans. Put it in the imbal account. */
orph = GetOrMakeAccount (acc, trans, _("Imbalance"));
/* put split into account before setting split value */
splat = xaccMallocSplit();
xaccAccountBeginEdit (orph);
xaccAccountInsertSplit (orph, splat);
xaccAccountCommitEdit (orph);
xaccTransBeginEdit (trans, 1);
DxaccSplitSetValue (splat, -imbalance);
xaccTransAppendSplit (trans, splat);
xaccTransCommitEdit (trans);
}
xaccTransScrubImbalance (trans);
}
}
void
xaccTransScrubImbalance (Transaction *trans)
{
GList *node;
Split *split;
Account *peer;
Account *account;
gnc_numeric imbalance;
imbalance = xaccTransGetImbalance (trans);
if (gnc_numeric_zero_p (imbalance))
return;
DEBUG ("Found imbalance");
peer = NULL;
for (node = trans->splits; node; node = node->next)
{
split = node->data;
peer = xaccSplitGetAccount (split);
if (peer)
break;
}
if (!peer)
{
PERR ("Transaction with no accounts");
return;
}
/* OK, we found an imbalanced trans. Put it in the imbal account. */
account = GetOrMakeAccount (peer, trans, _("Imbalance"));
/* put split into account before setting split value */
split = xaccMallocSplit();
xaccAccountBeginEdit (account);
xaccAccountInsertSplit (account, split);
xaccAccountCommitEdit (account);
xaccTransBeginEdit (trans, TRUE);
xaccSplitSetValue (split, gnc_numeric_neg (imbalance));
xaccTransAppendSplit (trans, split);
xaccTransCommitEdit (trans);
}
/* ================================================================ */
static Account *
@ -166,27 +194,29 @@ GetOrMakeAccount (Account *peer, Transaction *trans, const char *name_root)
/* build the account name */
currency = xaccTransFindCommonCurrency (trans);
accname = alloca (strlen (name_root) +
strlen (gnc_commodity_get_mnemonic(currency)) + 2);
strcpy (accname, name_root);
strcat (accname, "-");
strcat (accname, gnc_commodity_get_mnemonic(currency));
accname = g_strconcat (name_root, "-",
gnc_commodity_get_mnemonic(currency), NULL);
/* see if we've got one of these going already ... */
acc = xaccGetPeerAccountFromName (peer, accname);
if (acc) return acc;
/* guess not. We'll have to build one */
acc = xaccMallocAccount ();
xaccAccountBeginEdit (acc);
xaccAccountSetName (acc, accname);
xaccAccountSetCurrency (acc, currency);
xaccAccountSetType (acc, BANK);
if (acc == NULL)
{
/* guess not. We'll have to build one */
acc = xaccMallocAccount ();
xaccAccountBeginEdit (acc);
xaccAccountSetName (acc, accname);
xaccAccountSetCurrency (acc, currency);
xaccAccountSetType (acc, BANK);
/* hang the account off the root */
root = xaccGetAccountRoot (peer);
xaccGroupInsertAccount (root, acc);
xaccAccountCommitEdit (acc);
/* hang the account off the root */
root = xaccGetAccountRoot (peer);
xaccGroupInsertAccount (root, acc);
xaccAccountCommitEdit (acc);
}
g_free (accname);
return acc;
}

View File

@ -62,6 +62,7 @@ void xaccGroupScrubOrphans (AccountGroup *grp);
* is created to offset this amount and is added to an "imbalance"
* account.
*/
void xaccTransScrubImbalance (Transaction *trans);
void xaccAccountScrubImbalance (Account *acc);
void xaccAccountTreeScrubImbalance (Account *acc);
void xaccGroupScrubImbalance (AccountGroup *grp);

View File

@ -959,12 +959,6 @@ ComputeValue (GList *splits, Split * skip_me,
return value;
}
double
DxaccTransGetImbalance (Transaction * trans)
{
return gnc_numeric_to_double(xaccTransGetImbalance(trans));
}
gnc_numeric
xaccTransGetImbalance (Transaction * trans)
{
@ -973,6 +967,52 @@ xaccTransGetImbalance (Transaction * trans)
return imbal;
}
Split *
xaccTransGetBalanceSplit (Transaction *trans)
{
Split *split;
kvp_value *kvp;
GUID *guid;
if (!trans)
return NULL;
kvp = kvp_frame_get_slot (xaccTransGetSlots (trans), "balance-split");
if (!kvp)
return NULL;
guid = kvp_value_get_guid (kvp);
if (!guid)
return NULL;
split = xaccSplitLookup (guid);
if (g_list_find (trans->splits, split))
return split;
xaccTransSetBalanceSplit (trans, NULL);
return NULL;
}
void
xaccTransSetBalanceSplit (Transaction *trans, Split *split)
{
kvp_value *new_value;
if (!trans)
return;
if (split)
new_value = kvp_value_new_guid (xaccSplitGetGUID (split));
else
new_value = NULL;
kvp_frame_set_slot(xaccTransGetSlots (trans), "balance-split", new_value);
if (new_value)
kvp_value_delete(new_value);
}
/********************************************************************\
\********************************************************************/
gboolean
@ -1129,7 +1169,7 @@ xaccSplitRebalance (Split *split)
{
Transaction *trans;
gnc_numeric value;
const gnc_commodity * base_currency = NULL;
const gnc_commodity * base_currency = NULL;
trans = split->parent;
@ -1358,7 +1398,7 @@ xaccTransCommitEdit (Transaction *trans)
xaccSplitSetShareAmount(s, gnc_numeric_neg(split->damount));
xaccSplitSetValue(s, gnc_numeric_neg(split->value));
}
trans->open &= ~DEFER_REBALANCE;
xaccTransRebalance (trans);

View File

@ -290,8 +290,14 @@ xaccTransIsCommonExclSCurrency (Transaction *trans,
* in the currency that is returned by the xaccTransFindCommonCurrency()
* method.
*/
double DxaccTransGetImbalance (Transaction * trans);
gnc_numeric xaccTransGetImbalance (Transaction * trans);
gnc_numeric xaccTransGetImbalance (Transaction * trans);
/* The xaccTransGetBalanceSplit method returns the 'balance' split of
* a transaction or NULL if there is no balance split. The balance
* split is an 'artificial' split created to make the transaction
* balance. This split is automatically managed by the rebalancing
* routines and is created and destroyed as needed. */
Split * xaccTransGetBalanceSplit (Transaction *trans);
/* ------------- splits --------------- */
Split * xaccMallocSplit (void);
@ -475,7 +481,7 @@ int xaccCountSplits (Split **sarray);
* The xaccGetAccountByFullName routine is similar, but uses
* full names using the given separator.
*/
Account * xaccGetAccountByName (Transaction *, const char *);
Account * xaccGetAccountByName (Transaction *trans, const char *name);
Account * xaccGetAccountByFullName (Transaction *trans,
const char *name,
const char separator);

View File

@ -230,6 +230,8 @@ void xaccFreeSplit (Split *split); /* frees memory */
void xaccSplitRebalance (Split *split);
/* Set the balance split of a transaction. */
void xaccTransSetBalanceSplit (Transaction *trans, Split *split);
/* FIXME: this is probably wrong, but it'll have to wait until Bill
returns. It's *ONLY* for file IO. Don't use these elsewhere. */