gnucash/libgnucash/engine/Split.h
Christopher Lam e79db92d8d [Split.c] xaccSplitListGetUniqueTransactionsReversed
Same as xaccSplitListGetUniqueTransactions but doesn't reverse the
list prior to returning. To be used by gnc-tree-model-split-reg.c

Several optimizations

* doesn't call g_list_find and g_list_append for every iteration
* uses g_hash_table to cache list of txns already added instead of g_list_find
* does not reverse the result, thereby returning a reversed list.
2021-02-24 09:08:25 +08:00

565 lines
22 KiB
C

/********************************************************************\
* 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 *
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
* Boston, MA 02110-1301, USA gnu@gnu.org *
* *
\********************************************************************/
/** @addtogroup Engine
@{ */
/** @addtogroup Transaction Transaction, Split
A good overview of transactions, splits and accounts can be
found in the texinfo documentation, together with an overview of
how to use this API.
@{ */
/** @file Split.h
@brief API for Transactions and Splits (journal entries)
@author Copyright (C) 1997 Robin D. Clark
@author Copyright (C) 1997-2001 Linas Vepstas <linas@linas.org>
*/
#ifndef XACC_SPLIT_H
#define XACC_SPLIT_H
typedef struct _SplitClass SplitClass;
#include <time.h>
#include "gnc-commodity.h"
#include "gnc-engine.h"
#ifdef __cplusplus
extern "C" {
#endif
/* --- type macros --- */
#define GNC_TYPE_SPLIT (gnc_split_get_type ())
#define GNC_SPLIT(o) \
(G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_SPLIT, Split))
#define GNC_SPLIT_CLASS(k) \
(G_TYPE_CHECK_CLASS_CAST((k), GNC_TYPE_SPLIT, SplitClass))
#define GNC_IS_SPLIT(o) \
(G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_SPLIT))
#define GNC_IS_SPLIT_CLASS(k) \
(G_TYPE_CHECK_CLASS_TYPE ((k), GNC_TYPE_SPLIT))
#define GNC_SPLIT_GET_CLASS(o) \
(G_TYPE_INSTANCE_GET_CLASS ((o), GNC_TYPE_SPLIT, SplitClass))
GType gnc_split_get_type(void);
/** @name Split Reconciled field values
If you change these
be sure to change gnc-ui-util.c:gnc_get_reconciled_str() and
associated functions
@{
*/
#define CREC 'c' /**< The Split has been cleared */
#define YREC 'y' /**< The Split has been reconciled */
#define FREC 'f' /**< frozen into accounting period */
#define NREC 'n' /**< not reconciled or cleared */
#define VREC 'v' /**< split is void */
/** @} */
/* Convert the amount/value of the Split for viewing in the account --
* in particular we want to convert the Split to be in to_commodity.
* Returns the amount.
*/
gnc_numeric xaccSplitConvertAmount (const Split *split, const Account * account);
/*-----------------------------------------------------------------------
* Splits
*-----------------------------------------------------------------------*/
/** @name Split general getters/setters
@{
*/
/** Constructor. */
Split * xaccMallocSplit (QofBook *book);
/* Reinit a previously malloc'd split. Split remains in the book it
was already in, and the QofInstance portions also remain unchanged.
It's basically the data elements that are reverted to default
values. */
void xaccSplitReinit(Split * split);
/** Destructor.
*
* The xaccSplitDestroy() method will update its parent account and
* transaction in a consistent manner, resulting in the complete
* unlinking of the split, and the freeing of its associated memory.
* The goal of this routine is to perform the removal and destruction
* of the split in an atomic fashion, with no chance of accidentally
* leaving the accounting structure out-of-balance or otherwise
* inconsistent.
*
* If the deletion of the split leaves the transaction with no splits,
* then the transaction will be marked for deletion. (It will not be
* deleted until the xaccTransCommitEdit() routine is called.)
*
* @return TRUE upon successful deletion of the split. FALSE when
* the parenting Transaction is a read-only one.
*/
gboolean xaccSplitDestroy (Split *split);
/*################## Added for Reg2 #################*/
/** This is really a helper for xaccTransCopyOnto. It doesn't reparent
* the 'to' split to from's transaction, because xaccTransCopyOnto is
* responsible for parenting the split to the correct transaction.
* Also, from's parent transaction may not even be a valid
* transaction, so this function may not modify anything about 'from'
* or from's transaction.
*/
void xaccSplitCopyOnto(const Split *from_split, Split *to_split);
/*################## Added for Reg2 #################*/
/** Returns the book of this split, i.e. the entity where this split
* is stored. */
QofBook * xaccSplitGetBook (const Split *split);
/** Returns the account of this split, which was set through
* xaccAccountInsertSplit(). */
Account * xaccSplitGetAccount (const Split *split);
void xaccSplitSetAccount (Split *s, Account *acc);
/** Returns the parent transaction of the split. */
Transaction * xaccSplitGetParent (const Split *split);
void xaccSplitSetParent (Split *split, Transaction *trans);
/** Returns the pointer to the debited/credited Lot where this split
* belongs to, or NULL if it doesn't belong to any. */
GNCLot * xaccSplitGetLot (const Split *split);
/** Assigns the split to a specific Lot */
void xaccSplitSetLot(Split* split, GNCLot* lot);
/** The memo is an arbitrary string associated with a split. It is
* intended to hold a short (zero to forty character) string that is
* displayed by the GUI along with this split. Users typically type
* in free form text from the GUI. */
void xaccSplitSetMemo (Split *split, const char *memo);
/** Returns the memo string. */
const char * xaccSplitGetMemo (const Split *split);
/** The Action is an arbitrary user-assigned string.
* The action field is an arbitrary user-assigned value.
* It is meant to be a very short (one to ten character) string that
* signifies the "type" of this split, such as e.g. Buy, Sell, Div,
* Withdraw, Deposit, ATM, Check, etc. The idea is that this field
* can be used to create custom reports or graphs of data. Note that the
* business features auto-fill this value, but doesn't depend on it. Rather than use
* this function directly, see 'gnc_set_num_action' in
* engine/engine-helpers.c & .h which takes a user-set book option for selecting
* the source for the num-cell (the transaction-number or the split-action field)
* in registers/reports into account automatically */
void xaccSplitSetAction (Split *split, const char *action);
/** Returns the action string. Rather than use this function directly, see
* 'gnc_get_num_action' and 'gnc_get_action_num'in
* engine/engine-helpers.c & .h which takes a user-set book option for selecting
* the source for the num-cell (the transaction-number or the split-action field)
* in registers/reports into account automatically */
const char * xaccSplitGetAction (const Split *split);
/** @} */
/** @name Split Date getters/setters
@{
*/
/** Set the reconcile flag. The Reconcile flag is a single char, whose
* values are typically are 'n', 'y', 'c'. In Transaction.h, macros
* are defined for typical values (e.g. CREC, YREC). */
void xaccSplitSetReconcile (Split *split, char reconciled_flag);
/** Returns the value of the reconcile flag. */
char xaccSplitGetReconcile (const Split *split);
/** Set the date on which this split was reconciled by specifying the
* time as time64. */
void xaccSplitSetDateReconciledSecs (Split *split, time64 time);
/*################## Added for Reg2 #################*/
/** Retrieve the date when the Split was reconciled. */
time64 xaccSplitGetDateReconciled (const Split *split);
/*################## Added for Reg2 #################*/
/** @} */
/** @name Split amount getters/setters
*
* 'value' vs. 'amount' of a Split: The 'value' is the amount of the
* _transaction_ balancing commodity (i.e. currency) involved,
* 'amount' is the amount of the _account's_ commodity involved.
@{
*/
/** The xaccSplitSetAmount() method sets the amount in the account's
* commodity that the split should have.
*
* The following four setter functions set the prices and amounts.
* All of the routines always maintain balance: that is, invoking any
* of them will cause other splits in the transaction to be modified
* so that the net value of the transaction is zero.
*
* IMPORTANT: The split should be parented by an account before
* any of these routines are invoked! This is because the actual
* setting of amounts/values requires SCU settings from the account.
* If these are not available, then amounts/values will be set to
* -1/0, which is an invalid value. I believe this order dependency
* is a bug, but I'm too lazy to find, fix & test at the moment ...
*
* @note If you use this on a newly created transaction, make sure
* that the 'value' is also set so that it doesn't remain zero.
*/
void xaccSplitSetAmount (Split *split, gnc_numeric amount);
/** Returns the amount of the split in the account's commodity.
* Note that for cap-gains splits, this is slaved to the transaction
* that is causing the gains to occur.
*/
gnc_numeric xaccSplitGetAmount (const Split * split);
/** The xaccSplitSetValue() method sets the value of this split in the
* transaction's commodity.
*
* @note If you use this on a newly created transaction, make sure
* that the 'amount' is also set so that it doesn't remain zero.
*/
void xaccSplitSetValue (Split *split, gnc_numeric value);
/** Returns the value of this split in the transaction's commodity.
* Note that for cap-gains splits, this is slaved to the transaction
* that is causing the gains to occur.
*/
gnc_numeric xaccSplitGetValue (const Split * split);
/** The xaccSplitSetSharePriceAndAmount() method will simultaneously
* update the share price and the number of shares. This is a utility
* routine that is equivalent to a xaccSplitSetSharePrice() followed
* by and xaccSplitSetAmount(), except that it incurs the processing
* overhead of balancing only once, instead of twice. */
void xaccSplitSetSharePriceAndAmount (Split *split,
gnc_numeric price,
gnc_numeric amount);
/** Returns the price of the split, that is, the value divided by the
* amount. If the amount is zero, returns a gnc_numeric of value
* one. */
gnc_numeric xaccSplitGetSharePrice (const Split * split);
/** Depending on the base_currency, set either the value or the amount
* of this split or both: If the base_currency is the transaction's
* commodity, set the value. If it is the account's commodity, set the
* amount. If both, set both.
*
* @note <b>WATCH OUT:</b> When using this function and the
* transaction's and account's commodities are different, the amount
* or the value will be left as zero. This might screw up the
* multi-currency handling code in the register. So please think twice
* whether you need this function -- using xaccSplitSetValue()
* together with xaccSplitSetAmount() is definitely the better and
* safer solution!
*/
void xaccSplitSetBaseValue (Split *split, gnc_numeric value,
const gnc_commodity * base_currency);
/** Depending on the base_currency, return either the value or the
* amount of this split: If the base_curreny is the transaction's
* commodity, return the value. If it is the account's commodity,
* return the amount. If it is neither print a warning message and
* return gnc_numeric_zero().
*/
gnc_numeric xaccSplitGetBaseValue (const Split *split,
const gnc_commodity * base_currency);
/** Returns the running balance up to and including the indicated split.
* The balance is the currency-denominated balance. For accounts
* with non-unit share prices, it is correctly adjusted for
* share prices.
*
* Returns the running balance up to & including the indicated split.
*/
gnc_numeric xaccSplitGetBalance (const Split *split);
/**
* The noclosing-balance is the currency-denominated balance of all
* transactions except 'closing' transactions. It is correctly
* adjusted for price fluctuations.
*
* Returns the running balance up to & including the indicated split.
*/
gnc_numeric xaccSplitGetNoclosingBalance (const Split *split);
/**
* The cleared-balance is the currency-denominated balance
* of all transactions that have been marked as cleared or reconciled.
* It is correctly adjusted for price fluctuations.
*
* Returns the running balance up to & including the indicated split.
*/
gnc_numeric xaccSplitGetClearedBalance (const Split *split);
/**
* Returns the reconciled-balance of this split. The
* reconciled-balance is the currency-denominated balance of all
* transactions that have been marked as reconciled.
*
* Returns the running balance up to & including the indicated split.
*/
gnc_numeric xaccSplitGetReconciledBalance (const Split *split);
/** @} */
/** @name Split utility functions
@{
*/
/** Equality.
*
* @param sa First split to compare
* @param sb Second split to compare
*
* @param check_guids If TRUE, try a guid_equal() on the GUIDs of both
* splits if their pointers are not equal in the first place.
*
* @param check_balances If TRUE, compare balances between the two
* splits. Balances are recalculated whenever a split is added or
* removed from an account, so YMMV on whether this should be set.
*
* @param check_txn_splits If the pointers are not equal, but
* everything else so far is equal (including memo, amount, value,
* kvp), then, when comparing the parenting transactions with
* xaccTransEqual(), set its argument check_splits to be TRUE.
*/
gboolean xaccSplitEqual(const Split *sa, const Split *sb,
gboolean check_guids,
gboolean check_balances,
gboolean check_txn_splits);
/** The xaccSplitLookup() subroutine will return the
* split associated with the given id, or NULL
* if there is no such split. */
Split * xaccSplitLookup (const GncGUID *guid, QofBook *book);
#define xaccSplitLookupDirect(g,b) xaccSplitLookup(&(g),b)
/*################## Added for Reg2 #################*/
/* Get a GList of unique transactions containing the given list of Splits. */
GList *xaccSplitListGetUniqueTransactionsReversed (const GList *splits);
GList *xaccSplitListGetUniqueTransactions(const GList *splits);
/*################## Added for Reg2 #################*/
/** Add a peer split to this split's lot-split list.
* @param other_split: The split whose guid to add
* @param timestamp: The time to be recorded for the split.
*/
void xaccSplitAddPeerSplit (Split *split, const Split *other_split,
const time64 timestamp);
/** Does this split have peers?
*/
gboolean xaccSplitHasPeers (const Split *split);
/** Report if a split is a peer of this one.
* @param other_split: The split to test for being a peer of this one.
* @return: True if other_split is registered as a peer of this one.
*/
gboolean xaccSplitIsPeerSplit (const Split *split, const Split *other_split);
/** Remove a peer split from this split's lot-split list.
* @param other_split: The split whose guid to remove
*/
void xaccSplitRemovePeerSplit (Split *split, const Split *other_split);
/** Merge the other_split's peer splits into split's peers.
* @param other_split: The split donating the peer splits.
*/
void xaccSplitMergePeerSplits (Split *split, const Split *other_split);
/**
* The xaccSplitGetOtherSplit() is a convenience routine that returns
* the other of a pair of splits. If there are more than two
* splits, it returns NULL.
*/
Split * xaccSplitGetOtherSplit (const Split *split);
/** The xaccIsPeerSplit() is a convenience routine that returns TRUE
* (a non-zero value) if the two splits share a common parent
* transaction, else it returns FALSE (zero).
*
gboolean xaccIsPeerSplit (const Split *split_1, const Split *split_2);
*/
/** Returns the split type, which is either the string "normal", or
* "stock-split" for a split from a stock split (pun intended? :-). */
const char *xaccSplitGetType(const Split *s);
/** Mark a split to be of type stock split - after this, you shouldn't
modify the value anymore, just the amount. */
void xaccSplitMakeStockSplit(Split *s);
/**
* The xaccSplitOrder(sa,sb) method is useful for sorting.
* if sa and sb have different transactions, return their xaccTransOrder
* return a negative value if split sa has a smaller currency-value than sb,
* return a positive value if split sa has a larger currency-value than sb,
* return a negative value if split sa has a smaller share-price than sb,
* return a positive value if split sa has a larger share-price than sb,
* then compares memo and action using the strcmp()
* c-library routine, returning what strcmp would return.
* Then it compares the reconciled flags, then the reconciled dates,
* Finally, it returns zero if all of the above match.
*/
gint xaccSplitOrder (const Split *sa, const Split *sb);
gint xaccSplitOrderDateOnly (const Split *sa, const Split *sb);
/*
* These functions compare two splits by different criteria.
*
* These functions were added because converting strings to guile
* for comparisons in the transaction report is terribly inefficient.
* More may be added here in future if it turns out that other types
* of comparisons also induces guile slowdowns.
*/
/** Compare two splits by full name of account. Returns similar to
* strcmp. */
int xaccSplitCompareAccountFullNames(const Split *sa, const Split *sb);
/** Compare two splits by code of account. Returns similar to
* strcmp. */
int xaccSplitCompareAccountCodes(const Split *sa, const Split *sb);
/** Compare two splits by full name of the other account. Returns
* similar to strcmp. This function attempts to find the split on the
* other side of a transaction and compare on it. */
int xaccSplitCompareOtherAccountFullNames(const Split *sa, const Split *sb);
/** Compare two splits by code of the other account. Returns similar
* to strcmp. This function attempts to find the split on the
* other side of a transaction and compare on it. */
int xaccSplitCompareOtherAccountCodes(const Split *sa, const Split *sb);
/**
* These functions take a split, get the corresponding split on the
* "other side" of the transaction, and extract either the name or code
* of that split, reverting to returning a constant "Split" if the
* transaction has more than one split on the "other side". These
* were added for the transaction report, and is in C because the code
* was already written in C for the above functions and duplication
* is silly.
*
* Note that this will only return a real value in case of a
* two-split transaction as that is the only situation in which
* a reliable value can be returned. In other situations
* "-- Split Transaction --" will be returned as Account Name
* or "Split" for Account Code.
*/
char * xaccSplitGetCorrAccountFullName(const Split *sa);
/** document me */
const char * xaccSplitGetCorrAccountName(const Split *sa);
/** document me */
const char * xaccSplitGetCorrAccountCode(const Split *sa);
#ifdef DUMP_FUNCTIONS
void xaccSplitDump (const Split *split, const char *tag);
#endif
/** @} */
/** @name Split deprecated functions
@{
*/
/** @deprecated The xaccSplitSetSharePrice() method sets the price of the
* split. DEPRECATED - set the value and amount instead. */
void xaccSplitSetSharePrice (Split *split, gnc_numeric price);
/** @} */
/********************************************************************\
* Miscellaneous utility routines.
\********************************************************************/
/** @name Split voiding
@{
*/
/** Returns the original pre-void amount of a split.
*
* @param split The split in question.
*
* @return A gnc_numeric containing the original value of this split.
* Returns a gnc_numeric of zero upon error.
*/
gnc_numeric xaccSplitVoidFormerAmount(const Split *split);
/** Returns the original pre-void value of a split.
*
* @param split The split in question.
*
* @return A gnc_numeric containing the original amount of this split.
* Returns a gnc_numeric of zero upon error.
*/
gnc_numeric xaccSplitVoidFormerValue(const Split *split);
/** @} */
/** @name Split Parameter names
* Note, if you want to get the equivalent of "ACCT_MATCH_ALL" you
* need to create a search on the following parameter list:
* SPLIT->SPLIT_TRANS->TRANS_SPLITLIST->SPLIT_ACCOUNT_GUID. If you do
* this, you might want to use the ACCOUNT_MATCH_ALL_TYPE as the
* override so the gnome-search dialog displays the right type.
@{
*/
#define SPLIT_DATE_RECONCILED "date-reconciled"
#define SPLIT_BALANCE "balance"
#define SPLIT_CLEARED_BALANCE "cleared-balance"
#define SPLIT_RECONCILED_BALANCE "reconciled-balance"
#define SPLIT_MEMO "memo"
#define SPLIT_ACTION "action"
#define SPLIT_RECONCILE "reconcile-flag"
#define SPLIT_AMOUNT "amount"
#define SPLIT_SHARE_PRICE "share-price"
#define SPLIT_VALUE "value"
#define SPLIT_TYPE "type"
#define SPLIT_VOIDED_AMOUNT "voided-amount"
#define SPLIT_VOIDED_VALUE "voided-value"
#define SPLIT_LOT "lot"
#define SPLIT_TRANS "trans"
#define SPLIT_ACCOUNT "account"
#define SPLIT_ACCOUNT_GUID "account-guid" /**< for guid_match_all */
/* used for SORTING ONLY */
#define SPLIT_ACCT_FULLNAME "acct-fullname"
#define SPLIT_CORR_ACCT_NAME "corr-acct-fullname"
#define SPLIT_CORR_ACCT_CODE "corr-acct-code"
/** @} */
/** \deprecated */
#define xaccSplitGetGUID(X) qof_entity_get_guid(QOF_INSTANCE(X))
/** \deprecated */
#define xaccSplitReturnGUID(X) (X ? *(qof_entity_get_guid(QOF_INSTANCE(X))) : *(guid_null()))
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* XACC_SPLIT_H */
/** @} */
/** @} */