59 #include <glib/gi18n.h> 65 #include "TransactionP.h" 68 #include "engine-helpers.h" 73 static QofLogModule log_module = GNC_MOD_LOT;
81 gnc_commodity *acc_comm;
84 if (!acc)
return FALSE;
92 for (node = splits; node; node = node->next)
94 Split *s = node->data;
95 Transaction *t = s->parent;
96 if (s->gains == GAINS_STATUS_GAINS)
continue;
97 if (acc_comm != t->common_currency)
return TRUE;
108 gnc_commodity *currency;
110 int (*numeric_pred)(gnc_numeric);
127 finder_helper (GNCLot *lot, gpointer user_data)
133 gboolean opening_is_positive, bal_is_positive;
139 if (s == NULL)
return NULL;
145 if (0 == (els->numeric_pred) (s->amount))
return NULL;
149 if (opening_is_positive != bal_is_positive)
return NULL;
154 trans->common_currency)))
159 posted = trans->date_posted;
160 if (els->date_pred (els->time, posted))
162 els->time = trans->date_posted;
169 static inline GNCLot *
170 xaccAccountFindOpenLot (
Account *acc, gnc_numeric sign,
171 gnc_commodity *currency,
178 es.currency = currency;
180 es.date_pred = date_pred;
191 gnc_commodity *currency)
194 ENTER (
" sign=%" G_GINT64_FORMAT
"/%" G_GINT64_FORMAT, sign.num,
197 lot = xaccAccountFindOpenLot (acc, sign, currency,
198 G_MAXINT64, earliest_pred);
205 xaccAccountFindLatestOpenLot (
Account *acc, gnc_numeric sign,
206 gnc_commodity *currency)
209 ENTER (
" sign=%" G_GINT64_FORMAT
"/%" G_GINT64_FORMAT,
210 sign.num, sign.denom);
212 lot = xaccAccountFindOpenLot (acc, sign, currency,
213 G_MININT64, latest_pred);
226 gboolean baln_is_positive, amt_is_positive;
228 if (!lot)
return split;
229 if (!split)
return NULL;
232 if (split->lot)
return NULL;
242 PWARN (
"split with zero amount; value=%s gflag=%x gsplit=%p",
246 if (split->gains_split)
248 PWARN (
"gains amt=%s value=%s",
266 PINFO (
"added split to empty lot, new lot baln=%s (%s)",
283 if ((baln_is_positive && amt_is_positive) ||
284 ((!baln_is_positive) && (!amt_is_positive)))
286 PWARN (
"accounting policy gave us split that enlarges the lot!\n" 287 "old lot baln=%s split amt=%s lot=%s",
315 PINFO (
"simple added split to lot, new lot baln=%s",
326 gnc_numeric amt_a, amt_b, amt_tot;
327 gnc_numeric val_a, val_b, val_tot;
333 trans = split->parent;
336 amt_tot = split->amount;
338 amt_b = gnc_numeric_sub_fixed (amt_tot, amt_a);
341 PINFO (
"++++++++++++++ splitting split=%p into amt = %s + %s",
349 val_tot = split->value;
353 gnc_numeric_denom(val_tot),
356 val_b = gnc_numeric_sub_fixed (val_tot, val_a);
359 PERR(
"Numeric overflow\n" 361 "\tval_tot=%s amt_a=%s amt_tot=%s\n",
371 PERR (
"Failed to split into two!");
374 PINFO (
"split value is = %s = %s + %s",
397 gnc_set_num_action(NULL, new_split, NULL, gnc_get_num_action(NULL, split));
431 gboolean splits_split_up = FALSE;
435 if (!split)
return FALSE;
440 if (split->lot)
return FALSE;
441 g_return_val_if_fail (split->gains == GAINS_STATUS_UNKNOWN ||
442 (split->gains & GAINS_STATUS_GAINS) == FALSE, FALSE);
449 ENTER (
"(split=%p)", split);
461 PINFO (
"have split %p amount=%s", split,
463 split->gains |= GAINS_STATUS_VDIRTY;
464 lot = pcy->PolicyGetLot (pcy, split);
471 if (split) splits_split_up = TRUE;
475 LEAVE (
" split_up=%d", splits_split_up);
476 return splits_split_up;
487 if (!split)
return NULL;
490 "gains-split", &gains_guid,
492 if (!gains_guid)
return NULL;
497 PINFO (
"split=%p has gains-split=%p", split, gains_split);
498 guid_free (gains_guid);
510 if (!split)
return NULL;
513 "gains-source", &source_guid,
515 if (!source_guid)
return NULL;
520 PINFO (
"split=%p has source-split=%p", split, source_split);
521 guid_free (source_guid);
533 gnc_commodity *currency = NULL;
534 gnc_numeric zero = gnc_numeric_zero();
537 gnc_numeric opening_amount, opening_value;
538 gnc_numeric lot_amount, lot_value;
539 gnc_commodity *opening_currency;
545 currency = split->parent->common_currency;
547 ENTER (
"(split=%p gains=%p status=0x%x lot=%s)", split,
551 xaccSplitDetermineGainStatus(split);
558 LEAVE (
"Currency transfer, gains not possible, returning.");
562 if (pcy->PolicyIsOpeningSplit (pcy, lot, split))
564 #if MOVE_THIS_TO_A_DATA_INTEGRITY_SCRUBBER 574 Transaction *trans = gains_split->parent;
575 PERR (
"Opening Split must not have cap gains!!\n");
582 LEAVE (
"Lot opening split, returning.");
588 LEAVE (
"Stock split split, returning.");
592 if (GAINS_STATUS_GAINS & split->gains)
595 PINFO (
"split is a gains recording split, switch over");
600 s = split->gains_split;
609 PERR (
"Bad gains-split pointer! .. trying to recover.");
611 s = split->gains_split;
613 #if MOVE_THIS_TO_A_DATA_INTEGRITY_SCRUBBER 625 Split *s = node->data;
626 if (pcy->PolicyIsOpeningSplit(pcy, lot, s))
628 if (GAINS_STATUS_UNKNOWN == s->gains) xaccSplitDetermineGainStatus (s);
629 if (s->gains & GAINS_STATUS_VDIRTY)
632 split->gains |= GAINS_STATUS_VDIRTY;
640 if ((FALSE == (split->gains & GAINS_STATUS_A_VDIRTY)) &&
641 (split->gains_split) &&
642 (FALSE == (split->gains_split->gains & GAINS_STATUS_A_VDIRTY)))
644 LEAVE (
"split not dirty, returning");
659 pcy->PolicyGetLotOpening (pcy, lot, &opening_amount, &opening_value,
670 LEAVE (
"Can't compute gains, mismatched commodities!");
688 PERR (
"Malformed Lot \"%s\"! (too thin!) " 689 "opening amt=%s split amt=%s baln=%s",
707 PERR (
"Malformed Lot \"%s\"! (too fat!) " 708 "opening amt=%s split amt=%s baln=%s",
729 gnc_numeric_denom(opening_value),
734 PINFO (
"Open amt=%s val=%s; split amt=%s val=%s; gains=%s\n",
742 PERR (
"Numeric overflow during gains calculation\n" 744 "\tOpen amt=%s val=%s\n\tsplit amt=%s val=%s\n\tgains=%s\n",
764 Split *lot_split, *gain_split;
765 gboolean new_gain_split;
773 lot_split = split->gains_split;
775 if (NULL == lot_split)
781 new_gain_split = TRUE;
787 if ((NULL == gain_acc) ||
830 trans = lot_split->parent;
837 new_gain_split = FALSE;
843 else if (split->gains_split == lot_split &&
844 lot_split->gains_split == split &&
845 gain_split->gains_split == split &&
851 new_gain_split = FALSE;
855 new_gain_split = TRUE;
862 PWARN (
"Resetting the transaction currency!");
882 split->gains = GAINS_STATUS_CLEAN;
883 split->gains_split = lot_split;
884 lot_split->gains = GAINS_STATUS_GAINS;
885 lot_split->gains_split = split;
886 gain_split->gains = GAINS_STATUS_GAINS;
887 gain_split->gains_split = split;
904 if (!split)
return gnc_numeric_zero();
905 ENTER(
"(split=%p)", split);
907 if (GAINS_STATUS_UNKNOWN == split->gains)
908 xaccSplitDetermineGainStatus(split);
909 if ((split->gains & GAINS_STATUS_A_VDIRTY) ||
910 (split->gains_split &&
911 (split->gains_split->gains & GAINS_STATUS_A_VDIRTY)))
919 if (!(GAINS_STATUS_GAINS & split->gains))
922 split = split->gains_split;
925 LEAVE(
"(split=%p)", split);
926 if (!split)
return gnc_numeric_zero();
934 xaccLotComputeCapGains (GNCLot *lot,
Account *gain_acc)
938 gboolean is_dirty = FALSE;
944 ENTER(
"(lot=%p)", lot);
948 Split *s = node->data;
949 if (pcy->PolicyIsOpeningSplit(pcy, lot, s))
951 if (GAINS_STATUS_UNKNOWN == s->gains)
952 xaccSplitDetermineGainStatus(s);
953 if (s->gains & GAINS_STATUS_VDIRTY)
956 s->gains &= ~GAINS_STATUS_VDIRTY;
965 Split *s = node->data;
966 s->gains |= GAINS_STATUS_VDIRTY;
972 Split *s = node->data;
975 LEAVE(
"(lot=%p)", lot);
void xaccSplitSetValue(Split *split, gnc_numeric val)
The xaccSplitSetValue() method sets the value of this split in the transaction's commodity.
GNCLot * xaccAccountFindEarliestOpenLot(Account *acc, gnc_numeric sign, gnc_commodity *currency)
The xaccAccountFindEarliestOpenLot() method is a handy utility routine for finding the earliest open ...
High-Level API for imposing Lot constraints.
void xaccSplitAddPeerSplit(Split *split, const Split *other_split, time64 timestamp)
Add a peer split to this split's lot-split list.
#define xaccTransAppendSplit(t, s)
Add a split to the transaction.
Transaction * xaccMallocTransaction(QofBook *book)
The xaccMallocTransaction() will malloc memory and initialize it.
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b represent the same number.
gchar * gnc_num_dbg_to_string(gnc_numeric n)
Convert to string.
void qof_instance_get(const QofInstance *inst, const gchar *first_prop,...)
Wrapper for g_object_get.
gpointer xaccAccountForEachLot(const Account *acc, gpointer(*proc)(GNCLot *lot, gpointer user_data), gpointer user_data)
The xaccAccountForEachLot() method will apply the function 'proc' to each lot in the account...
SplitList * xaccAccountGetSplitList(const Account *acc)
The xaccAccountGetSplitList() routine returns a pointer to a GList of the splits in the account...
QofBook * qof_instance_get_book(gconstpointer inst)
Return the book pointer.
gboolean xaccAccountIsPriced(const Account *acc)
Returns true if the account is a stock, mutual fund or currency, otherwise false. ...
QofInstance * qof_collection_lookup_entity(const QofCollection *col, const GncGUID *guid)
Find the entity going only from its guid.
#define PINFO(format, args...)
Print an informational note.
Utilities to Convert Stock Accounts to use Lots.
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value...
All arguments are required to have the same denominator, that denominator is to be used in the output...
void qof_instance_set(QofInstance *inst, const gchar *first_prop,...)
Wrapper for g_object_set Group setting multiple parameters in a single begin/commit/rollback.
char xaccSplitGetReconcile(const Split *split)
Returns the value of the reconcile flag.
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equal.
void xaccSplitComputeCapGains(Split *split, Account *gain_acc)
The xaccSplitComputeCapGains() routine computes the cap gains or losses for the indicated split...
void gnc_lot_add_split(GNCLot *lot, Split *split)
The gnc_lot_add_split() routine adds a split to this lot.
void xaccTransSetDescription(Transaction *trans, const char *desc)
Sets the transaction Description.
gboolean xaccAccountHasTrades(const Account *acc)
The xaccAccountHasTrades() method checks to see if the indicated account is used in the trading of co...
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
Split * xaccSplitGetGainsSourceSplit(const Split *split)
The xaccSplitGetGainsSourceSplit() routine returns the split that is the source of the cap gains in t...
void xaccSplitSetReconcile(Split *split, char recn)
Set the reconcile flag.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
QofCollection * qof_instance_get_collection(gconstpointer ptr)
Return the collection this instance belongs to.
Use any denominator which gives an exactly correct ratio of numerator to denominator.
gnc_numeric xaccSplitGetCapGains(Split *split)
The xaccSplitGetCapGains() method returns the value of capital gains (if any) associated with the ind...
int gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
Returns 1 if a>b, -1 if b>a, 0 if a == b.
#define PERR(format, args...)
Log a serious error.
#define ENTER(format, args...)
Print a function entry debugging message.
Split * xaccSplitGetCapGainsSplit(const Split *split)
The xaccSplitGetCapGainsSplit() routine returns the split that records the cap gains for this split...
Split * gnc_lot_get_earliest_split(GNCLot *lot)
The gnc_lot_get_earliest_split() routine is a convenience routine that helps identify the earliest da...
gboolean gnc_numeric_negative_p(gnc_numeric a)
Returns 1 if a < 0, otherwise returns 0.
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Set a new currency on a transaction.
const char * gnc_lot_get_title(const GNCLot *lot)
Get and set the account title, or the account notes, or the marker.
void xaccTransDestroy(Transaction *trans)
Destroys a transaction.
#define PWARN(format, args...)
Log a warning.
GList SplitList
GList of Split.
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account's commodity that the split should have...
Reduce the result value by common factor elimination, using the smallest possible value for the denom...
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Multiply a times b, returning the product.
void xaccSplitSetMemo(Split *split, const char *memo)
The memo is an arbitrary string associated with a split.
Implement Accounting Policy.
Implement Accounting Policy Private header File.
SplitList * gnc_lot_get_split_list(const GNCLot *lot)
The gnc_lot_get_split_list() routine returns a GList of all the splits in this lot.
time64 xaccTransRetDatePosted(const Transaction *trans)
Retrieve the posted date of the transaction.
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
void gnc_lot_get_balance_before(const GNCLot *lot, const Split *split, gnc_numeric *amount, gnc_numeric *value)
The gnc_lot_get_balance_before routine computes both the balance and value in the lot considering onl...
gnc_numeric gnc_numeric_abs(gnc_numeric a)
Returns a newly created gnc_numeric that is the absolute value of the given gnc_numeric value...
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
gnc_numeric gnc_numeric_div(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Division.
#define xaccSplitGetGUID(X)
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
All type declarations for the whole Gnucash engine.
gboolean gnc_numeric_positive_p(gnc_numeric a)
Returns 1 if a > 0, otherwise returns 0.
Split * xaccMallocSplit(QofBook *book)
Constructor.
gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Return a-b.
Split * xaccSplitAssignToLot(Split *split, GNCLot *lot)
The xaccSplitAssignToLot() routine will fit the indicated split into the indicated lot...
void xaccSplitSetDateReconciledSecs(Split *split, time64 secs)
Set the date on which this split was reconciled by specifying the time as time64. ...
time64 xaccSplitGetDateReconciled(const Split *split)
Retrieve the date when the Split was reconciled.
void xaccTransSetDatePostedSecs(Transaction *trans, time64 secs)
The xaccTransSetDatePostedSecs() method will modify the posted date of the transaction, specified by a time64 (see ctime(3)).
gboolean xaccTransGetVoidStatus(const Transaction *trans)
Retrieve information on whether or not a transaction has been voided.
GNCLot * gnc_lot_make_default(Account *acc)
XXX: Document?
gboolean xaccSplitAssign(Split *split)
The`xaccSplitAssign() routine will take the indicated split and, if it doesn't already belong to a lo...
gboolean gnc_lot_is_closed(GNCLot *lot)
The gnc_lot_is_closed() routine returns a boolean flag: is this lot closed? A lot is closed if its ba...
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction's commodity.
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity.
#define xaccAccountInsertSplit(acc, s)
The xaccAccountInsertSplit() method will insert the indicated split into the indicated account...
This is the private header for the account structure.
Split * xaccSplitGetOtherSplit(const Split *split)
The xaccSplitGetOtherSplit() is a convenience routine that returns the other of a pair of splits...
#define LEAVE(format, args...)
Print a function exit debugging message.
Account * xaccAccountGainsAccount(Account *acc, gnc_commodity *curr)
Retrieve the gains account used by this account for the indicated currency, creating and recording a ...
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
time64 gnc_time(time64 *tbuf)
get the current time
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.
const char * xaccSplitGetMemo(const Split *split)
Returns the memo string.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Account * gnc_lot_get_account(const GNCLot *lot)
The gnc_lot_get_account() routine returns the account with which this lot is associated.
void xaccTransSetDateEnteredSecs(Transaction *trans, time64 secs)
Modify the date of when the transaction was entered.
const char * xaccSplitGetType(const Split *s)
The xaccIsPeerSplit() is a convenience routine that returns TRUE (a non-zero value) if the two splits...
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
#define GNC_DENOM_AUTO
Values that can be passed as the 'denom' argument.
API for Transactions and Splits (journal entries)
The type used to store guids in C.
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Utilities to Automatically Compute Capital Gains/Losses.
GNCPolicy * gnc_account_get_policy(Account *acc)
Get the account's lot order policy.
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equivalent.
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
The gnc_lot_get_balance() routine returns the balance of the lot.
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account's commodity.