59 #include <glib/gi18n.h>
65 #include "TransactionP.h"
68 #include "engine-helpers.h"
84 if (!acc)
return FALSE;
92 for (node = splits; node; node = node->next)
94 Split *s = node->data;
96 if (s->gains == GAINS_STATUS_GAINS)
continue;
97 if (acc_comm != t->common_currency)
return TRUE;
117 return ((earl.tv_sec > tran.tv_sec) ||
118 ((earl.tv_sec == tran.tv_sec) && (earl.tv_nsec > tran.tv_nsec)));
124 return ((earl.tv_sec < tran.tv_sec) ||
125 ((earl.tv_sec == tran.tv_sec) && (earl.tv_nsec < tran.tv_nsec)));
129 finder_helper (
GNCLot *lot, gpointer user_data)
135 gboolean opening_is_positive, bal_is_positive;
140 if (s == NULL)
return NULL;
146 if (0 == (els->numeric_pred) (s->amount))
return NULL;
150 if (opening_is_positive != bal_is_positive)
return NULL;
155 trans->common_currency)))
160 if (els->date_pred (els->ts, trans->date_posted))
162 els->ts = trans->date_posted;
178 es.currency = currency;
179 es.ts.tv_sec = guess;
181 es.date_pred = date_pred;
195 ENTER (
" sign=%" G_GINT64_FORMAT
"/%" G_GINT64_FORMAT, sign.num,
198 lot = xaccAccountFindOpenLot (acc, sign, currency,
199 G_MAXINT64, earliest_pred);
210 ENTER (
" sign=%" G_GINT64_FORMAT
"/%" G_GINT64_FORMAT,
211 sign.num, sign.denom);
213 lot = xaccAccountFindOpenLot (acc, sign, currency,
214 G_MININT64, latest_pred);
227 gboolean baln_is_positive, amt_is_positive;
229 if (!lot)
return split;
230 if (!split)
return NULL;
233 if (split->lot)
return NULL;
243 PWARN (
"split with zero amount; value=%s gflag=%x gsplit=%p",
247 if (split->gains_split)
249 PWARN (
"gains amt=%s value=%s",
267 PINFO (
"added split to empty lot, new lot baln=%s (%s)",
284 if ((baln_is_positive && amt_is_positive) ||
285 ((!baln_is_positive) && (!amt_is_positive)))
287 PWARN (
"accounting policy gave us split that enlarges the lot!\n"
288 "old lot baln=%s split amt=%s lot=%s",
316 PINFO (
"simple added split to lot, new lot baln=%s",
335 trans = split->parent;
338 amt_tot = split->amount;
340 amt_b = gnc_numeric_sub_fixed (amt_tot, amt_a);
343 PINFO (
"++++++++++++++ splitting split=%p into amt = %s + %s",
351 val_tot = split->value;
355 gnc_numeric_denom(val_tot),
358 val_b = gnc_numeric_sub_fixed (val_tot, val_a);
361 PERR(
"Numeric overflow\n"
363 "\tval_tot=%s amt_a=%s amt_tot=%s\n",
373 PERR (
"Failed to split into two!");
376 PINFO (
"split value is = %s = %s + %s",
399 gnc_set_num_action(NULL, new_split, NULL, gnc_get_num_action(NULL, split));
441 gboolean splits_split_up = FALSE;
445 if (!split)
return FALSE;
450 if (split->lot)
return FALSE;
451 g_assert (split->gains == GAINS_STATUS_UNKNOWN ||
452 (split->gains & GAINS_STATUS_GAINS) == FALSE);
459 ENTER (
"(split=%p)", split);
471 PINFO (
"have split %p amount=%s", split,
473 split->gains |= GAINS_STATUS_VDIRTY;
474 lot = pcy->PolicyGetLot (pcy, split);
481 if (split) splits_split_up = TRUE;
485 LEAVE (
" split_up=%d", splits_split_up);
486 return splits_split_up;
497 if (!split)
return NULL;
500 "gains-split", &gains_guid,
502 if (!gains_guid)
return NULL;
507 PINFO (
"split=%p has gains-split=%p", split, gains_split);
519 if (!split)
return NULL;
522 "gains-source", &source_guid,
524 if (!source_guid)
return NULL;
529 PINFO (
"split=%p has source-split=%p", split, source_split);
553 currency = split->parent->common_currency;
555 ENTER (
"(split=%p gains=%p status=0x%x lot=%s)", split,
559 xaccSplitDetermineGainStatus(split);
566 LEAVE (
"Currency transfer, gains not possible, returning.");
570 if (pcy->PolicyIsOpeningSplit (pcy, lot, split))
572 #if MOVE_THIS_TO_A_DATA_INTEGRITY_SCRUBBER
583 PERR (
"Opening Split must not have cap gains!!\n");
590 LEAVE (
"Lot opening split, returning.");
596 LEAVE (
"Stock split split, returning.");
600 if (GAINS_STATUS_GAINS & split->gains)
603 PINFO (
"split is a gains recording split, switch over");
608 s = split->gains_split;
617 PERR (
"Bad gains-split pointer! .. trying to recover.");
619 s = split->gains_split;
621 #if MOVE_THIS_TO_A_DATA_INTEGRITY_SCRUBBER
633 Split *s = node->data;
634 if (pcy->PolicyIsOpeningSplit(pcy, lot, s))
636 if (GAINS_STATUS_UNKNOWN == s->gains) xaccSplitDetermineGainStatus (s);
637 if (s->gains & GAINS_STATUS_VDIRTY)
640 split->gains |= GAINS_STATUS_VDIRTY;
648 if ((FALSE == (split->gains & GAINS_STATUS_A_VDIRTY)) &&
649 (split->gains_split) &&
650 (FALSE == (split->gains_split->gains & GAINS_STATUS_A_VDIRTY)))
652 LEAVE (
"split not dirty, returning");
667 pcy->PolicyGetLotOpening (pcy, lot, &opening_amount, &opening_value,
678 LEAVE (
"Can't compute gains, mismatched commodities!");
696 PERR (
"Malformed Lot \"%s\"! (too thin!) "
697 "opening amt=%s split amt=%s baln=%s",
715 PERR (
"Malformed Lot \"%s\"! (too fat!) "
716 "opening amt=%s split amt=%s baln=%s",
737 gnc_numeric_denom(opening_value),
742 PINFO (
"Open amt=%s val=%s; split amt=%s val=%s; gains=%s\n",
750 PERR (
"Numeric overflow during gains calculation\n"
752 "\tOpen amt=%s val=%s\n\tsplit amt=%s val=%s\n\tgains=%s\n",
772 Split *lot_split, *gain_split;
774 gboolean new_gain_split;
782 lot_split = split->gains_split;
784 if (NULL == lot_split)
790 new_gain_split = TRUE;
796 if ((NULL == gain_acc) ||
839 trans = lot_split->parent;
846 new_gain_split = FALSE;
852 else if (split->gains_split == lot_split &&
853 lot_split->gains_split == split &&
854 gain_split->gains_split == split &&
860 new_gain_split = FALSE;
864 new_gain_split = TRUE;
871 PWARN (
"Resetting the transaction currency!");
891 split->gains = GAINS_STATUS_CLEAN;
892 split->gains_split = lot_split;
893 lot_split->gains = GAINS_STATUS_GAINS;
894 lot_split->gains_split = split;
895 gain_split->gains = GAINS_STATUS_GAINS;
896 gain_split->gains_split = split;
913 if (!split)
return gnc_numeric_zero();
914 ENTER(
"(split=%p)", split);
916 if (GAINS_STATUS_UNKNOWN == split->gains)
917 xaccSplitDetermineGainStatus(split);
918 if ((split->gains & GAINS_STATUS_A_VDIRTY) ||
919 (split->gains_split &&
920 (split->gains_split->gains & GAINS_STATUS_A_VDIRTY)))
928 if (!(GAINS_STATUS_GAINS & split->gains))
931 split = split->gains_split;
934 LEAVE(
"(split=%p)", split);
935 if (!split)
return gnc_numeric_zero();
947 gboolean is_dirty = FALSE;
953 ENTER(
"(lot=%p)", lot);
957 Split *s = node->data;
958 if (pcy->PolicyIsOpeningSplit(pcy, lot, s))
960 if (GAINS_STATUS_UNKNOWN == s->gains)
961 xaccSplitDetermineGainStatus(s);
962 if (s->gains & GAINS_STATUS_VDIRTY)
965 s->gains &= ~GAINS_STATUS_VDIRTY;
974 Split *s = node->data;
975 s->gains |= GAINS_STATUS_VDIRTY;
981 Split *s = node->data;
984 LEAVE(
"(lot=%p)", lot);
void xaccSplitSetValue(Split *s, gnc_numeric amt)
GNCLot * xaccAccountFindEarliestOpenLot(Account *acc, gnc_numeric sign, gnc_commodity *currency)
High-Level API for imposing Lot constraints.
#define xaccTransAppendSplit(t, s)
Transaction * xaccMallocTransaction(QofBook *book)
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
gchar * gnc_num_dbg_to_string(gnc_numeric n)
void qof_instance_get(const QofInstance *inst, const gchar *first_param,...)
Wrapper for g_object_get.
gpointer xaccAccountForEachLot(const Account *acc, gpointer(*proc)(GNCLot *lot, gpointer user_data), gpointer user_data)
SplitList * xaccAccountGetSplitList(const Account *acc)
QofBook * qof_instance_get_book(gconstpointer)
gboolean xaccAccountIsPriced(const Account *acc)
QofInstance * qof_collection_lookup_entity(const QofCollection *, const GncGUID *)
#define PINFO(format, args...)
Utilities to Convert Stock Accounts to use Lots.
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Timespec xaccSplitRetDateReconciledTS(const Split *split)
void qof_instance_set(QofInstance *inst, const gchar *first_param,...)
Wrapper for g_object_set Group setting multiple parameters in a single begin/commit/rollback.
char xaccSplitGetReconcile(const Split *split)
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
void xaccSplitComputeCapGains(Split *split, Account *gain_acc)
void gnc_lot_add_split(GNCLot *lot, Split *split)
void xaccTransSetDescription(Transaction *trans, const char *desc)
gboolean xaccAccountHasTrades(const Account *acc)
Use a 64-bit unsigned int timespec.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Split * xaccSplitGetGainsSourceSplit(const Split *split)
void xaccSplitSetReconcile(Split *split, char recn)
Transaction * xaccSplitGetParent(const Split *split)
QofCollection * qof_instance_get_collection(gconstpointer inst)
gnc_numeric xaccSplitGetCapGains(Split *split)
gint gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
#define PERR(format, args...)
#define ENTER(format, args...)
Split * xaccSplitGetCapGainsSplit(const Split *split)
Split * gnc_lot_get_earliest_split(GNCLot *lot)
gboolean gnc_numeric_negative_p(gnc_numeric a)
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
const char * gnc_lot_get_title(const GNCLot *lot)
void xaccTransDestroy(Transaction *trans)
#define PWARN(format, args...)
void xaccSplitSetAmount(Split *s, gnc_numeric amt)
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
void xaccSplitSetMemo(Split *split, const char *memo)
Implement Accounting Policy.
Implement Accounting Policy Private header File.
SplitList * gnc_lot_get_split_list(const GNCLot *lot)
const char * xaccTransGetDescription(const Transaction *trans)
void gnc_lot_get_balance_before(const GNCLot *lot, const Split *split, gnc_numeric *amount, gnc_numeric *value)
gnc_numeric gnc_numeric_abs(gnc_numeric a)
void xaccTransCommitEdit(Transaction *trans)
gnc_numeric gnc_numeric_div(gnc_numeric x, gnc_numeric y, gint64 denom, gint how)
#define xaccSplitGetGUID(X)
void xaccTransBeginEdit(Transaction *trans)
All type declarations for the whole Gnucash engine.
gboolean gnc_numeric_positive_p(gnc_numeric a)
struct _gnc_numeric gnc_numeric
An rational-number type.
Split * xaccMallocSplit(QofBook *book)
gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Split * xaccSplitAssignToLot(Split *split, GNCLot *lot)
gboolean xaccTransGetVoidStatus(const Transaction *trans)
GNCLot * gnc_lot_make_default(Account *acc)
gboolean xaccSplitAssign(Split *split)
gboolean gnc_lot_is_closed(GNCLot *lot)
gnc_numeric xaccSplitGetValue(const Split *split)
void xaccAccountBeginEdit(Account *acc)
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
#define xaccAccountInsertSplit(acc, s)
Timespec xaccTransRetDatePostedTS(const Transaction *trans)
Split * xaccSplitGetOtherSplit(const Split *split)
#define LEAVE(format, args...)
Account * xaccAccountGainsAccount(Account *acc, gnc_commodity *curr)
void xaccSplitSetDateReconciledTS(Split *split, Timespec *ts)
time64 gnc_time(time64 *tbuf)
get the current local time
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
const char * xaccSplitGetMemo(const Split *split)
Account * gnc_lot_get_account(const GNCLot *lot)
void xaccTransSetDateEnteredSecs(Transaction *trans, time64 secs)
const char * xaccSplitGetType(const Split *s)
const char * xaccAccountGetName(const Account *acc)
API for Transactions and Splits (journal entries)
void xaccAccountCommitEdit(Account *acc)
Utilities to Automatically Compute Capital Gains/Losses.
GNCPolicy * gnc_account_get_policy(Account *acc)
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
const gchar * QofLogModule
void xaccTransSetDatePostedTS(Transaction *trans, const Timespec *ts)
gnc_numeric xaccSplitGetAmount(const Split *split)