mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
fix how double-entry is maintained
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@698 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
78eab15914
commit
1742d0fc7a
@ -34,6 +34,14 @@
|
|||||||
#include "TransactionP.h"
|
#include "TransactionP.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* if the "force_double_entry" flag has a non-zero value,
|
||||||
|
* then all transactions will be *forced* to balance.
|
||||||
|
* This will be forced even if it requires a new split
|
||||||
|
* to be created.
|
||||||
|
*/
|
||||||
|
int force_double_entry = 0;
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
* Because I can't use C++ for this project, doesn't mean that I *
|
* Because I can't use C++ for this project, doesn't mean that I *
|
||||||
* can't pretend too! These functions perform actions on the *
|
* can't pretend too! These functions perform actions on the *
|
||||||
@ -155,7 +163,7 @@ void xaccSplitSetShareAmount (Split *s, double amt)
|
|||||||
s -> damount = amt;
|
s -> damount = amt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xaccSplitSetAmount (Split *s, double amt)
|
void xaccSplitSetValue (Split *s, double amt)
|
||||||
{
|
{
|
||||||
MARK_SPLIT(s);
|
MARK_SPLIT(s);
|
||||||
/* remember, damount is actually share price */
|
/* remember, damount is actually share price */
|
||||||
@ -268,30 +276,92 @@ xaccFreeTransaction( Transaction *trans )
|
|||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
|
|
||||||
void
|
void
|
||||||
xaccTransRecomputeAmount (Transaction *trans)
|
xaccSplitRebalance (Split *split)
|
||||||
{
|
{
|
||||||
|
Transaction *trans;
|
||||||
Split *s;
|
Split *s;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
double amount = 0.0;
|
double value = 0.0;
|
||||||
|
|
||||||
s = trans->dest_splits[i];
|
|
||||||
while (s) {
|
|
||||||
amount += s->share_price * s->damount;
|
|
||||||
i++;
|
|
||||||
s = trans->dest_splits[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if there is just one split, then the credited
|
trans = split->parent;
|
||||||
* and the debited splits should match up. */
|
|
||||||
if (1 == i) {
|
if (&(trans->source_split) == split) {
|
||||||
|
/* The indicated split is the source split.
|
||||||
|
* Pick a destination split (by default,
|
||||||
|
* the first destination split), and force
|
||||||
|
* the total on it.
|
||||||
|
*/
|
||||||
|
|
||||||
s = trans->dest_splits[0];
|
s = trans->dest_splits[0];
|
||||||
trans -> source_split.damount = - (s->damount);
|
if (s) {
|
||||||
trans -> source_split.share_price = s->share_price;
|
/* first, add the source split */
|
||||||
|
value = split->share_price * split->damount;
|
||||||
|
|
||||||
|
/* now add in the sum of the destination splits */
|
||||||
|
i = 0;
|
||||||
|
while (s) {
|
||||||
|
value += s->share_price * s->damount;
|
||||||
|
i++;
|
||||||
|
s = trans->dest_splits[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* subtract the first destination split */
|
||||||
|
s = trans->dest_splits[0];
|
||||||
|
value -= (s->share_price) * (s->damount);
|
||||||
|
|
||||||
|
/* the new value of the destination split
|
||||||
|
* will be the result.
|
||||||
|
*/
|
||||||
|
s -> damount = - (value / (s->share_price));
|
||||||
|
MARK_SPLIT (s);
|
||||||
|
|
||||||
|
} else{
|
||||||
|
/* There are no destination splits !!
|
||||||
|
* Either this is allowed, in which case
|
||||||
|
* we just blow it off, or its forbidden,
|
||||||
|
* in which case we force a balacing split
|
||||||
|
* to be created.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (force_double_entry) {
|
||||||
|
value = split->share_price * split->damount;
|
||||||
|
|
||||||
|
/* malloc a new split, mirror it to the source split */
|
||||||
|
s = xaccMallocSplit ();
|
||||||
|
s->damount = -value;
|
||||||
|
free (s->memo);
|
||||||
|
s->memo = strdup (split->memo);
|
||||||
|
free (s->action);
|
||||||
|
s->action = strdup (split->action);
|
||||||
|
|
||||||
|
/* insert the new split into the transaction and
|
||||||
|
* the same account as the source split */
|
||||||
|
xaccTransAppendSplit (trans, s);
|
||||||
|
xaccAccountInsertSplit (split->acc, s);
|
||||||
|
MARK_SPLIT (s);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
trans -> source_split.damount = -amount;
|
|
||||||
trans -> source_split.share_price = 1.0;
|
/* The indicated split is a destination split.
|
||||||
|
* Compute grand total of all distination splits,
|
||||||
|
* and force the source split to blanace.
|
||||||
|
*/
|
||||||
|
i = 0;
|
||||||
|
s = trans->dest_splits[i];
|
||||||
|
value = 0.0;
|
||||||
|
while (s) {
|
||||||
|
value += s->share_price * s->damount;
|
||||||
|
i++;
|
||||||
|
s = trans->dest_splits[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
s = &(trans->source_split);
|
||||||
|
s -> damount = - (value / (s->share_price));
|
||||||
|
MARK_SPLIT (s);
|
||||||
}
|
}
|
||||||
MARK_SPLIT (&(trans->source_split));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
@ -343,9 +413,6 @@ xaccTransRemoveSplit (Transaction *trans, Split *split)
|
|||||||
s = trans->dest_splits[n];
|
s = trans->dest_splits[n];
|
||||||
}
|
}
|
||||||
trans->dest_splits[i] = NULL;
|
trans->dest_splits[i] = NULL;
|
||||||
|
|
||||||
/* bring dollar amounts into synchrony */
|
|
||||||
xaccTransRecomputeAmount (trans);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
|
@ -83,10 +83,33 @@ void xaccTransSetReconcile (Transaction *, char);
|
|||||||
void xaccTransAppendSplit (Transaction *, Split *);
|
void xaccTransAppendSplit (Transaction *, Split *);
|
||||||
void xaccTransRemoveSplit (Transaction *, Split *);
|
void xaccTransRemoveSplit (Transaction *, Split *);
|
||||||
|
|
||||||
/* recompute the total transaction value, based
|
/*
|
||||||
* on the sum of the debit splits that belong to this
|
* The xaccSplitRebalance() routine is an important routine for
|
||||||
* transaction. */
|
* maintaining and ensuring that double-entries balance properly.
|
||||||
void xaccTransRecomputeAmount (Transaction *);
|
* This routine forces the sum-total of the values of all the
|
||||||
|
* splits in a transaction to total up to exactly zero.
|
||||||
|
*
|
||||||
|
* It is worthwhile to understand the algorithm that this routine
|
||||||
|
* uses to acheive balance. It goes like this:
|
||||||
|
* If the indicated split is a destination split, then the
|
||||||
|
* total value of the destination splits is computed, and the
|
||||||
|
* value of the source split is adjusted to be minus this amount.
|
||||||
|
* (the share price of the source split is not changed).
|
||||||
|
* If the indicated split is the source split, then the value
|
||||||
|
* of the very first destination split is adjusted so that
|
||||||
|
* the blanace is zero. If there is not destination split,
|
||||||
|
* one of two outcomes are possible, depending on whether
|
||||||
|
* "forced_double_entry" is enabled or disabled.
|
||||||
|
* (1) if forced-double-entry is disabled, the fact that
|
||||||
|
* the destination is missing is ignored.
|
||||||
|
* (2) if force-double-entry is enabled, then a destination
|
||||||
|
* split that exactly mirrors the ource split is created,
|
||||||
|
* and credited to the same account as the source split.
|
||||||
|
* Hopefully, the user will notice this, and reparent the
|
||||||
|
* destination split properly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void xaccSplitRebalance (Split *);
|
||||||
|
|
||||||
/* ------------- gets --------------- */
|
/* ------------- gets --------------- */
|
||||||
/* return pointer to the source split */
|
/* return pointer to the source split */
|
||||||
@ -115,7 +138,7 @@ void xaccSplitSetAction (Split *, const char *);
|
|||||||
void xaccSplitSetReconcile (Split *, char);
|
void xaccSplitSetReconcile (Split *, char);
|
||||||
|
|
||||||
/* The following two functions set the amount on the split */
|
/* The following two functions set the amount on the split */
|
||||||
void xaccSplitSetAmount (Split *, double);
|
void xaccSplitSetValue (Split *, double);
|
||||||
void xaccSplitSetShareAmount (Split *, double);
|
void xaccSplitSetShareAmount (Split *, double);
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user