2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************\
|
2006-02-22 15:52:46 -06:00
|
|
|
* Transaction.c -- transaction implementation *
|
2001-08-07 18:36:04 -05:00
|
|
|
* Copyright (C) 1997 Robin D. Clark *
|
2003-09-01 15:20:52 -05:00
|
|
|
* Copyright (C) 1997-2003 Linas Vepstas <linas@linas.org> *
|
2001-08-07 18:36:04 -05:00
|
|
|
* Copyright (C) 2000 Bill Gribble <grib@billgribble.com> *
|
2006-01-23 00:38:20 -06:00
|
|
|
* Copyright (c) 2006 David Hampton <hampton@employees.org> *
|
2001-08-07 18:36:04 -05:00
|
|
|
* *
|
|
|
|
* 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 *
|
2005-11-16 23:35:02 -06:00
|
|
|
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
|
|
|
|
* Boston, MA 02110-1301, USA gnu@gnu.org *
|
2001-08-07 18:36:04 -05:00
|
|
|
* *
|
|
|
|
\********************************************************************/
|
|
|
|
|
2017-10-26 04:14:21 -05:00
|
|
|
#include <config.h>
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2015-05-22 21:50:25 -05:00
|
|
|
#include <platform.h>
|
|
|
|
#if PLATFORM(WINDOWS)
|
|
|
|
#include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
2005-11-19 17:53:34 -06:00
|
|
|
#include <glib.h>
|
|
|
|
#include <glib/gi18n.h>
|
2003-05-28 19:24:39 -05:00
|
|
|
#include <stdlib.h>
|
2001-08-07 18:36:04 -05:00
|
|
|
#include <string.h>
|
2018-11-11 02:43:24 -06:00
|
|
|
#include <stdint.h>
|
2001-08-07 18:36:04 -05:00
|
|
|
#include <time.h>
|
2010-02-25 11:42:43 -06:00
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
# include <unistd.h>
|
|
|
|
#endif
|
2001-08-07 18:36:04 -05:00
|
|
|
|
|
|
|
#include "AccountP.h"
|
2003-09-20 22:41:32 -05:00
|
|
|
#include "Scrub.h"
|
2003-09-20 17:53:28 -05:00
|
|
|
#include "Scrub3.h"
|
2001-08-07 18:36:04 -05:00
|
|
|
#include "TransactionP.h"
|
2006-02-22 15:52:46 -06:00
|
|
|
#include "SplitP.h"
|
2001-08-07 18:36:04 -05:00
|
|
|
#include "TransLog.h"
|
2003-09-01 15:20:52 -05:00
|
|
|
#include "cap-gains.h"
|
2001-08-07 18:36:04 -05:00
|
|
|
#include "gnc-commodity.h"
|
|
|
|
#include "gnc-engine.h"
|
2003-06-15 22:48:59 -05:00
|
|
|
#include "gnc-lot.h"
|
2006-03-03 21:21:34 -06:00
|
|
|
#include "gnc-event.h"
|
2017-08-05 06:54:28 -05:00
|
|
|
#include <gnc-date.h>
|
2014-12-26 15:28:22 -06:00
|
|
|
#include "SchedXaction.h"
|
2016-03-25 06:10:10 -05:00
|
|
|
#include "gncBusiness.h"
|
2016-02-16 19:11:55 -06:00
|
|
|
#include <qofinstance-p.h>
|
2017-11-13 12:15:04 -06:00
|
|
|
#include "gncInvoice.h"
|
|
|
|
#include "gncOwner.h"
|
2006-03-03 18:10:12 -06:00
|
|
|
|
|
|
|
/* Notes about xaccTransBeginEdit(), xaccTransCommitEdit(), and
|
|
|
|
* xaccTransRollback():
|
|
|
|
*
|
|
|
|
* Why use it:
|
|
|
|
*
|
|
|
|
* Data consistency: Wrapping your changes to financial data inside
|
|
|
|
* a BeginEdit/CommitEdit block allows the engine to verify that
|
|
|
|
* your changes still leave the financial objects in an internally
|
|
|
|
* consistent state. This is true even though you may make a series
|
|
|
|
* of individual changes that are not consistent by themselves. In
|
|
|
|
* this way, it's like telling the engine, "Okay, I've finished my
|
|
|
|
* edits. Please check my work."
|
|
|
|
*
|
|
|
|
* Data integrity: The other benefit of the BeginEdit/CommitEdit
|
|
|
|
* block is that it allows the engine (and the backend) to remember
|
|
|
|
* the last known correct state of your data. This allows you to
|
|
|
|
* undo any changes that you don't want to keep. In this way, it's
|
|
|
|
* like telling the engine telling the back end, "Yes, I really mean
|
|
|
|
* it. Remember this data." or "Nevermind, scratch that." The
|
|
|
|
* important feature here is that if things go bad, for whatever
|
|
|
|
* reason (e.g. the application crashed, you lost the backend), your
|
|
|
|
* data remains in the state it was in just after the previous
|
|
|
|
* xaccTransCommitEdit(). [assuming no nesting, which probably
|
|
|
|
* isn't useful outside the engine.]
|
|
|
|
*
|
|
|
|
* Note that the backend doesn't care about data consistency -
|
|
|
|
* that's the engine's job.
|
|
|
|
*
|
|
|
|
* Example Use:
|
|
|
|
*
|
|
|
|
* xaccTransBeginEdit(trans);
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* split = xaccMallocSplit(book);
|
|
|
|
* xaccSplitSetAccount(split, acc);
|
|
|
|
* xaccSplitSetParent(split, trans); // Adding a new split
|
|
|
|
*
|
|
|
|
* xaccSplitSetValue(split, val); // Changing a split
|
|
|
|
*
|
|
|
|
* xaccSplitDestroy(split); // Removing a split
|
|
|
|
*
|
|
|
|
* xaccTransSetNum(trans, "501"); // Changing the trans
|
|
|
|
*
|
|
|
|
* if (really_do_it)
|
|
|
|
* xaccTransCommitEdit(trans);
|
|
|
|
* else
|
|
|
|
* xaccTransRollbackEdit(trans);
|
|
|
|
*
|
|
|
|
* How it works:
|
|
|
|
*
|
|
|
|
* Calling xaccTransBeginEdit() starts a BeginEdit/CommitEdit block.
|
|
|
|
* Inside the block any changes to the transaction or any splits in
|
|
|
|
* the transaction are considered "pending". What does that mean?
|
|
|
|
*
|
|
|
|
* In general that means that if you set and then get the
|
|
|
|
* transaction's or split's parameters inside the
|
|
|
|
* BeginEdit/CommitEdit block, you'll get the values you just set.
|
|
|
|
* However, if you change an object's many-to-one relationship with
|
|
|
|
* another object, you won't see the change from the "many" side
|
|
|
|
* until the CommitEdit. For example, if you move a split from one
|
|
|
|
* account into another, you can see the change with
|
|
|
|
* xaccSplitGetAccount(), but both Accounts' split lists won't be
|
|
|
|
* updated until the CommitEdit. Correspondingly, no signals
|
|
|
|
* (events) will be generated for those "foreign" objects, or the
|
|
|
|
* Transaction, until the CommitEdit.
|
|
|
|
*
|
|
|
|
* This behavior is important because, when we're finally ready to
|
|
|
|
* commit to the backend, we can't be 100% sure that the backend
|
|
|
|
* will still be available. We have to offer the backend all of the
|
|
|
|
* new state as if it were already "true", but we need to save all of
|
|
|
|
* the old state in case the backend won't accept our commit. If
|
|
|
|
* the backend commit fails, we have to restore all the old state.
|
|
|
|
* If the backend commit succeeds, and *only* after it succeeds, we
|
|
|
|
* can advertise the new state to the rest of the engine (and gui).
|
|
|
|
*
|
|
|
|
* Q: Who owns the ref of an added split if the Transaction is rolled
|
|
|
|
* back?
|
|
|
|
*
|
|
|
|
* A: This is a design decision. If the answer is 'the user',
|
|
|
|
* then the burden is on the api user to check the transaction after
|
|
|
|
* every commit to see if the added split is really in the
|
|
|
|
* transaction. If they don't they risk leaking the split if the
|
|
|
|
* commit was rolled back. Another design is to answer 'the engine'.
|
|
|
|
* In that case the burden is on the engine to free a newly added
|
|
|
|
* split if the commit is rolled back. Unfortunately the engine
|
|
|
|
* objects aren't ref-counted, so this is tricky.
|
|
|
|
*
|
|
|
|
* In the current implementation, the answer is 'the engine', but
|
|
|
|
* that means that you must not add the split to two different
|
|
|
|
* transactions during the begin/commit block, because if one rolls
|
|
|
|
* back, they will both think they own the split. This is one
|
|
|
|
* specific example of the general problem that the outcome of two
|
|
|
|
* parallel begin/commit edit blocks for two transactions where edits
|
|
|
|
* for both transactions involve the same splits and one or more
|
|
|
|
* edit-blocks is rolled-back, is poorly-defined.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*
|
2010-03-02 15:40:28 -06:00
|
|
|
* Design notes on event-generation: transaction-modified-events
|
2006-03-03 18:10:12 -06:00
|
|
|
* should not be generated until transaction commit or rollback
|
2010-03-02 15:40:28 -06:00
|
|
|
* time. They should not be generated as each field is tweaked.
|
2003-09-03 08:02:37 -05:00
|
|
|
* This for two reasons:
|
2006-03-03 18:10:12 -06:00
|
|
|
* 1) Most editing events make multiple changes to a transaction,
|
2003-09-03 08:02:37 -05:00
|
|
|
* which would generate a flurry of (needless) events, if they
|
|
|
|
* weren't saved up till the commit.
|
2010-03-02 15:40:28 -06:00
|
|
|
* 2) Technically, its incorrect to use transaction data
|
2017-01-16 16:03:50 -06:00
|
|
|
* until the transaction is committed. The GUI element that
|
2003-09-03 08:02:37 -05:00
|
|
|
* is changing the data can look at it, but all of the rest
|
2017-01-16 16:03:50 -06:00
|
|
|
* of the GUI should ignore the data until its committed.
|
2003-09-03 08:02:37 -05:00
|
|
|
*/
|
|
|
|
|
2003-06-15 22:48:59 -05:00
|
|
|
const char *trans_notes_str = "notes";
|
2001-10-01 00:42:23 -05:00
|
|
|
const char *void_reason_str = "void-reason";
|
2001-10-08 20:47:55 -05:00
|
|
|
const char *void_time_str = "void-time";
|
2003-06-15 22:48:59 -05:00
|
|
|
const char *void_former_notes_str = "void-former-notes";
|
2010-12-15 20:11:53 -06:00
|
|
|
const char *trans_is_closing_str = "book_closing";
|
2021-02-05 13:52:33 -06:00
|
|
|
const char *doclink_uri_str = "assoc_uri"; // this is the old name for the document link, kept for compatibility
|
2001-10-01 00:42:23 -05:00
|
|
|
|
2001-11-26 22:47:19 -06:00
|
|
|
/* KVP entry for date-due value */
|
2003-09-01 15:20:52 -05:00
|
|
|
#define TRANS_DATE_DUE_KVP "trans-date-due"
|
|
|
|
#define TRANS_TXN_TYPE_KVP "trans-txn-type"
|
|
|
|
#define TRANS_READ_ONLY_REASON "trans-read-only"
|
2006-05-03 19:06:58 -05:00
|
|
|
#define TRANS_REVERSED_BY "reversed-by"
|
2014-05-07 08:37:14 -05:00
|
|
|
#define GNC_SX_FROM "from-sched-xaction"
|
2001-11-26 22:47:19 -06:00
|
|
|
|
2003-09-30 12:53:33 -05:00
|
|
|
#define ISO_DATELENGTH 32 /* length of an iso 8601 date string. */
|
2001-10-08 20:47:55 -05:00
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/* This static indicates the debugging module that this .o belongs to. */
|
2005-11-01 21:32:36 -06:00
|
|
|
static QofLogModule log_module = GNC_MOD_ENGINE;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
2014-05-07 08:37:14 -05:00
|
|
|
PROP_CURRENCY, /* Table */
|
|
|
|
PROP_NUM, /* Table */
|
|
|
|
PROP_POST_DATE, /* Table */
|
|
|
|
PROP_ENTER_DATE, /* Table */
|
|
|
|
PROP_DESCRIPTION, /* Table */
|
|
|
|
PROP_INVOICE, /* KVP */
|
|
|
|
PROP_SX_TXN, /* KVP */
|
|
|
|
PROP_ONLINE_ACCOUNT,/* KVP */
|
2010-02-28 11:35:53 -06:00
|
|
|
};
|
|
|
|
|
2012-05-26 18:47:34 -05:00
|
|
|
void
|
|
|
|
check_open (const Transaction *trans)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (trans && 0 >= qof_instance_get_editlevel(trans))
|
|
|
|
PERR ("transaction %p not open for editing", trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
2006-03-03 18:10:12 -06:00
|
|
|
gboolean
|
|
|
|
xaccTransStillHasSplit(const Transaction *trans, const Split *s)
|
|
|
|
{
|
2013-08-16 11:43:58 -05:00
|
|
|
return (s && s->parent == trans && !qof_instance_get_destroying(s));
|
2006-03-03 18:10:12 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Executes 'cmd_block' for each split currently in the transaction,
|
|
|
|
* using the in-edit state. Use the variable 's' for each split. */
|
2013-08-16 11:43:58 -05:00
|
|
|
#define FOR_EACH_SPLIT(trans, cmd_block) if (trans->splits) { \
|
2006-03-03 18:10:12 -06:00
|
|
|
GList *splits; \
|
|
|
|
for (splits = (trans)->splits; splits; splits = splits->next) { \
|
|
|
|
Split *s = splits->data; \
|
|
|
|
if (xaccTransStillHasSplit(trans, s)) { \
|
|
|
|
cmd_block; \
|
|
|
|
} \
|
|
|
|
} \
|
2013-08-16 11:43:58 -05:00
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2019-09-10 18:33:33 -05:00
|
|
|
static inline void mark_trans (Transaction *trans);
|
2005-11-01 21:32:36 -06:00
|
|
|
void mark_trans (Transaction *trans)
|
2001-11-25 04:59:26 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
FOR_EACH_SPLIT(trans, mark_split(s));
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2019-09-10 18:33:33 -05:00
|
|
|
static inline void gen_event_trans (Transaction *trans);
|
2005-11-01 21:32:36 -06:00
|
|
|
void gen_event_trans (Transaction *trans)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *node;
|
2006-05-07 23:56:17 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
for (node = trans->splits; node; node = node->next)
|
2003-09-03 08:02:37 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
Split *s = node->data;
|
|
|
|
Account *account = s->acc;
|
|
|
|
GNCLot *lot = s->lot;
|
|
|
|
if (account)
|
|
|
|
qof_event_gen (&account->inst, GNC_EVENT_ITEM_CHANGED, s);
|
|
|
|
|
|
|
|
if (lot)
|
|
|
|
{
|
|
|
|
/* A change of transaction date might affect opening date of lot */
|
|
|
|
qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_MODIFY, NULL);
|
|
|
|
}
|
2003-09-03 08:02:37 -05:00
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2007-04-04 19:23:58 -05:00
|
|
|
/* GObject Initialization */
|
2010-02-28 11:35:53 -06:00
|
|
|
G_DEFINE_TYPE(Transaction, gnc_transaction, QOF_TYPE_INSTANCE)
|
2007-04-04 19:23:58 -05:00
|
|
|
|
|
|
|
static void
|
2010-02-28 11:35:53 -06:00
|
|
|
gnc_transaction_init(Transaction* trans)
|
2007-04-04 19:23:58 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER ("trans=%p", trans);
|
|
|
|
/* Fill in some sane defaults */
|
|
|
|
trans->num = CACHE_INSERT("");
|
|
|
|
trans->description = CACHE_INSERT("");
|
|
|
|
trans->common_currency = NULL;
|
|
|
|
trans->splits = NULL;
|
2017-12-31 06:37:02 -06:00
|
|
|
trans->date_entered = 0;
|
|
|
|
trans->date_posted = 0;
|
2010-03-02 15:40:28 -06:00
|
|
|
trans->marker = 0;
|
|
|
|
trans->orig = NULL;
|
2018-09-09 15:49:52 -05:00
|
|
|
trans->readonly_reason = NULL;
|
|
|
|
trans->reason_cache_valid = FALSE;
|
2018-12-31 07:48:26 -06:00
|
|
|
trans->isClosingTxn_cached = -1;
|
2010-03-02 15:40:28 -06:00
|
|
|
LEAVE (" ");
|
2007-04-04 19:23:58 -05:00
|
|
|
}
|
|
|
|
|
2007-04-04 22:10:26 -05:00
|
|
|
static void
|
2010-02-28 11:35:53 -06:00
|
|
|
gnc_transaction_dispose(GObject *txnp)
|
2007-04-04 22:10:26 -05:00
|
|
|
{
|
2010-02-28 11:35:53 -06:00
|
|
|
G_OBJECT_CLASS(gnc_transaction_parent_class)->dispose(txnp);
|
2007-04-04 22:10:26 -05:00
|
|
|
}
|
|
|
|
|
2007-04-04 19:23:58 -05:00
|
|
|
static void
|
2010-02-28 11:35:53 -06:00
|
|
|
gnc_transaction_finalize(GObject* txnp)
|
2007-04-04 19:23:58 -05:00
|
|
|
{
|
2010-02-28 11:35:53 -06:00
|
|
|
G_OBJECT_CLASS(gnc_transaction_parent_class)->finalize(txnp);
|
2007-04-04 19:23:58 -05:00
|
|
|
}
|
|
|
|
|
2013-09-24 15:11:24 -05:00
|
|
|
/* Note that g_value_set_object() refs the object, as does
|
|
|
|
* g_object_get(). But g_object_get() only unrefs once when it disgorges
|
|
|
|
* the object, leaving an unbalanced ref, which leaks. So instead of
|
|
|
|
* using g_value_set_object(), use g_value_take_object() which doesn't
|
|
|
|
* ref the object when used in get_property().
|
|
|
|
*/
|
2010-02-28 11:35:53 -06:00
|
|
|
static void
|
|
|
|
gnc_transaction_get_property(GObject* object,
|
2010-03-02 15:40:28 -06:00
|
|
|
guint prop_id,
|
|
|
|
GValue* value,
|
|
|
|
GParamSpec* pspec)
|
2010-02-28 11:35:53 -06:00
|
|
|
{
|
|
|
|
Transaction* tx;
|
2014-05-07 08:37:14 -05:00
|
|
|
gchar *key;
|
2018-08-02 20:19:15 -05:00
|
|
|
Time64 time;
|
2010-02-28 11:35:53 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_return_if_fail(GNC_IS_TRANSACTION(object));
|
2010-02-28 11:35:53 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
tx = GNC_TRANSACTION(object);
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_NUM:
|
2010-02-28 11:35:53 -06:00
|
|
|
g_value_set_string(value, tx->num);
|
2010-03-02 15:40:28 -06:00
|
|
|
break;
|
|
|
|
case PROP_DESCRIPTION:
|
2010-02-28 11:35:53 -06:00
|
|
|
g_value_set_string(value, tx->description);
|
2010-03-02 15:40:28 -06:00
|
|
|
break;
|
2010-03-01 10:46:49 -06:00
|
|
|
case PROP_CURRENCY:
|
2013-09-24 15:11:24 -05:00
|
|
|
g_value_take_object(value, tx->common_currency);
|
2010-03-02 15:40:28 -06:00
|
|
|
break;
|
2010-03-01 10:46:49 -06:00
|
|
|
case PROP_POST_DATE:
|
2018-08-02 20:19:15 -05:00
|
|
|
time.t = tx->date_posted;
|
|
|
|
g_value_set_boxed(value, &time);
|
2010-03-02 15:40:28 -06:00
|
|
|
break;
|
2010-03-01 10:46:49 -06:00
|
|
|
case PROP_ENTER_DATE:
|
2018-08-02 20:19:15 -05:00
|
|
|
time.t = tx->date_entered;
|
|
|
|
g_value_set_boxed(value, &time);
|
2010-03-02 15:40:28 -06:00
|
|
|
break;
|
2014-05-07 08:37:14 -05:00
|
|
|
case PROP_INVOICE:
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (tx), value, 2, GNC_INVOICE_ID, GNC_INVOICE_GUID);
|
2017-11-02 14:42:22 -05:00
|
|
|
break;
|
2014-05-07 08:37:14 -05:00
|
|
|
case PROP_SX_TXN:
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (tx), value, 1, GNC_SX_FROM);
|
2017-11-02 14:42:22 -05:00
|
|
|
break;
|
2014-05-07 08:37:14 -05:00
|
|
|
case PROP_ONLINE_ACCOUNT:
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (tx), value, 1, "online_id");
|
2017-11-02 14:42:22 -05:00
|
|
|
break;
|
2010-02-28 11:35:53 -06:00
|
|
|
default:
|
2010-03-02 15:40:28 -06:00
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
2011-12-08 11:11:21 -06:00
|
|
|
break;
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
2010-02-28 11:35:53 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gnc_transaction_set_property(GObject* object,
|
2010-03-02 15:40:28 -06:00
|
|
|
guint prop_id,
|
|
|
|
const GValue* value,
|
|
|
|
GParamSpec* pspec)
|
2010-02-28 11:35:53 -06:00
|
|
|
{
|
|
|
|
Transaction* tx;
|
2014-05-07 08:37:14 -05:00
|
|
|
gchar *key;
|
2018-08-02 15:29:47 -05:00
|
|
|
Time64 *t;
|
2010-02-28 11:35:53 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_return_if_fail(GNC_IS_TRANSACTION(object));
|
2010-02-28 11:35:53 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
tx = GNC_TRANSACTION(object);
|
2014-05-07 08:37:14 -05:00
|
|
|
g_assert (qof_instance_get_editlevel(tx));
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_NUM:
|
2010-02-28 11:35:53 -06:00
|
|
|
xaccTransSetNum( tx, g_value_get_string(value));
|
2010-03-02 15:40:28 -06:00
|
|
|
break;
|
|
|
|
case PROP_DESCRIPTION:
|
2010-02-28 11:35:53 -06:00
|
|
|
xaccTransSetDescription(tx, g_value_get_string(value));
|
2010-03-02 15:40:28 -06:00
|
|
|
break;
|
2010-03-01 10:46:49 -06:00
|
|
|
case PROP_CURRENCY:
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransSetCurrency(tx, g_value_get_object(value));
|
|
|
|
break;
|
2010-03-01 10:46:49 -06:00
|
|
|
case PROP_POST_DATE:
|
2018-08-02 15:29:47 -05:00
|
|
|
t = (Time64*)g_value_get_boxed(value);
|
|
|
|
xaccTransSetDatePostedSecs(tx, t->t);
|
2010-03-02 15:40:28 -06:00
|
|
|
break;
|
2010-03-01 10:46:49 -06:00
|
|
|
case PROP_ENTER_DATE:
|
2018-08-02 15:29:47 -05:00
|
|
|
t = (Time64*)g_value_get_boxed(value);
|
|
|
|
xaccTransSetDateEnteredSecs(tx, t->t);
|
2010-03-02 15:40:28 -06:00
|
|
|
break;
|
2014-05-07 08:37:14 -05:00
|
|
|
case PROP_INVOICE:
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (tx), value, 2, GNC_INVOICE_ID, GNC_INVOICE_GUID);
|
2017-11-02 14:42:22 -05:00
|
|
|
break;
|
2014-05-07 08:37:14 -05:00
|
|
|
case PROP_SX_TXN:
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (tx), value, 1, GNC_SX_FROM);
|
2017-11-02 14:42:22 -05:00
|
|
|
break;
|
2014-05-07 08:37:14 -05:00
|
|
|
case PROP_ONLINE_ACCOUNT:
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (tx), value, 1, "online_id");
|
2017-11-02 14:42:22 -05:00
|
|
|
break;
|
2010-02-28 11:35:53 -06:00
|
|
|
default:
|
2010-03-02 15:40:28 -06:00
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
2011-12-08 11:11:21 -06:00
|
|
|
break;
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
2010-02-28 11:35:53 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gnc_transaction_class_init(TransactionClass* klass)
|
|
|
|
{
|
|
|
|
GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gobject_class->dispose = gnc_transaction_dispose;
|
|
|
|
gobject_class->finalize = gnc_transaction_finalize;
|
|
|
|
gobject_class->set_property = gnc_transaction_set_property;
|
|
|
|
gobject_class->get_property = gnc_transaction_get_property;
|
|
|
|
|
|
|
|
g_object_class_install_property
|
|
|
|
(gobject_class,
|
|
|
|
PROP_NUM,
|
|
|
|
g_param_spec_string("num",
|
|
|
|
"Transaction Number",
|
|
|
|
"The transactionNumber is an arbitrary string "
|
|
|
|
"assigned by the user. It is intended to be "
|
|
|
|
"a short 1-6 character string that is displayed "
|
|
|
|
"by the register. For checks, it is usually the "
|
|
|
|
"check number. For other types of transactions, "
|
|
|
|
"it can be any string.",
|
|
|
|
NULL,
|
|
|
|
G_PARAM_READWRITE));
|
|
|
|
|
|
|
|
g_object_class_install_property
|
|
|
|
(gobject_class,
|
|
|
|
PROP_DESCRIPTION,
|
|
|
|
g_param_spec_string("description",
|
|
|
|
"Transaction Description",
|
|
|
|
"The transaction description is an arbitrary string "
|
|
|
|
"assigned by the user. It is usually the customer, "
|
|
|
|
"vendor or other organization associated with the "
|
|
|
|
"transaction.",
|
|
|
|
NULL,
|
|
|
|
G_PARAM_READWRITE));
|
2010-03-01 10:46:49 -06:00
|
|
|
|
|
|
|
g_object_class_install_property
|
2010-03-02 15:40:28 -06:00
|
|
|
(gobject_class,
|
|
|
|
PROP_CURRENCY,
|
|
|
|
g_param_spec_object ("currency",
|
|
|
|
"Currency",
|
|
|
|
"The base currency for this transaction.",
|
|
|
|
GNC_TYPE_COMMODITY,
|
|
|
|
G_PARAM_READWRITE));
|
2010-03-01 10:46:49 -06:00
|
|
|
|
|
|
|
g_object_class_install_property
|
2010-03-02 15:40:28 -06:00
|
|
|
(gobject_class,
|
|
|
|
PROP_POST_DATE,
|
|
|
|
g_param_spec_boxed("post-date",
|
|
|
|
"Post Date",
|
|
|
|
"The date the transaction occurred.",
|
2018-08-02 15:29:47 -05:00
|
|
|
GNC_TYPE_TIME64,
|
2010-03-02 15:40:28 -06:00
|
|
|
G_PARAM_READWRITE));
|
2010-03-01 10:46:49 -06:00
|
|
|
|
|
|
|
g_object_class_install_property
|
2010-03-02 15:40:28 -06:00
|
|
|
(gobject_class,
|
|
|
|
PROP_ENTER_DATE,
|
|
|
|
g_param_spec_boxed("enter-date",
|
|
|
|
"Enter Date",
|
|
|
|
"The date the transaction was entered.",
|
2018-08-02 15:29:47 -05:00
|
|
|
GNC_TYPE_TIME64,
|
2010-03-02 15:40:28 -06:00
|
|
|
G_PARAM_READWRITE));
|
2014-05-07 08:37:14 -05:00
|
|
|
|
|
|
|
g_object_class_install_property(
|
|
|
|
gobject_class,
|
|
|
|
PROP_INVOICE,
|
|
|
|
g_param_spec_boxed("invoice",
|
|
|
|
"Invoice attached to lot",
|
|
|
|
"Used by GncInvoice",
|
|
|
|
GNC_TYPE_GUID,
|
|
|
|
G_PARAM_READWRITE));
|
|
|
|
|
|
|
|
g_object_class_install_property(
|
|
|
|
gobject_class,
|
|
|
|
PROP_SX_TXN,
|
|
|
|
g_param_spec_boxed("from-sched-xaction",
|
|
|
|
"From Scheduled Transaction",
|
|
|
|
"Used by Scheduled Transastions to record the "
|
|
|
|
"originating template transaction for created "
|
|
|
|
"transactions",
|
|
|
|
GNC_TYPE_GUID,
|
|
|
|
G_PARAM_READWRITE));
|
|
|
|
|
|
|
|
g_object_class_install_property
|
|
|
|
(gobject_class,
|
|
|
|
PROP_ONLINE_ACCOUNT,
|
|
|
|
g_param_spec_string ("online-id",
|
|
|
|
"Online Account ID",
|
|
|
|
"The online account which corresponds to this "
|
|
|
|
"account for OFX/HCBI import",
|
|
|
|
NULL,
|
|
|
|
G_PARAM_READWRITE));
|
2010-02-28 11:35:53 -06:00
|
|
|
}
|
2007-04-04 19:23:58 -05:00
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************\
|
|
|
|
* xaccInitTransaction
|
|
|
|
* Initialize a transaction structure
|
|
|
|
\********************************************************************/
|
|
|
|
|
|
|
|
static void
|
2003-06-24 19:52:46 -05:00
|
|
|
xaccInitTransaction (Transaction * trans, QofBook *book)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER ("trans=%p", trans);
|
|
|
|
qof_instance_init_data (&trans->inst, GNC_ID_TRANS, book);
|
|
|
|
LEAVE (" ");
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
|
|
|
|
|
|
|
Transaction *
|
2003-06-24 19:52:46 -05:00
|
|
|
xaccMallocTransaction (QofBook *book)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
Transaction *trans;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_return_val_if_fail (book, NULL);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
trans = g_object_new(GNC_TYPE_TRANSACTION, NULL);
|
|
|
|
xaccInitTransaction (trans, book);
|
|
|
|
qof_event_gen (&trans->inst, QOF_EVENT_CREATE, NULL);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return trans;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2012-09-10 22:29:39 -05:00
|
|
|
#ifdef DUMP_FUNCTIONS
|
|
|
|
/* Please don't delete this function. Although it is not called by
|
|
|
|
any other code in GnuCash, it is useful when debugging. For example
|
|
|
|
it can be called using the gdb "call" command when stopped at a
|
|
|
|
breakpoint. */
|
|
|
|
void
|
|
|
|
xaccTransDump (const Transaction *trans, const char *tag)
|
|
|
|
{
|
|
|
|
GList *node;
|
2019-09-09 16:44:10 -05:00
|
|
|
char datebuff[MAX_DATE_LENGTH + 1];
|
2012-09-10 22:29:39 -05:00
|
|
|
|
|
|
|
printf("%s Trans %p", tag, trans);
|
2018-08-02 20:19:15 -05:00
|
|
|
memset(datebuff, 0, sizeof(datebuff));
|
2019-09-09 16:44:10 -05:00
|
|
|
qof_print_date_buff(datebuff, MAX_DATE_LENGTH, trans->date_entered);
|
2018-08-02 20:19:15 -05:00
|
|
|
printf(" Entered: %s\n", datebuff);
|
|
|
|
memset(datebuff, 0, sizeof(datebuff));
|
2019-09-09 16:44:10 -05:00
|
|
|
qof_print_date_buff(datebuff, MAX_DATE_LENGTH, trans->date_posted);
|
2018-08-02 20:19:15 -05:00
|
|
|
printf(" Posted: %s\n", datebuff);
|
2012-09-10 22:29:39 -05:00
|
|
|
printf(" Num: %s\n", trans->num ? trans->num : "(null)");
|
|
|
|
printf(" Description: %s\n",
|
|
|
|
trans->description ? trans->description : "(null)");
|
|
|
|
printf(" Currency: %s\n",
|
|
|
|
gnc_commodity_get_printname(trans->common_currency));
|
|
|
|
printf(" version: %x\n", qof_instance_get_version(trans));
|
|
|
|
printf(" version_chk: %x\n", qof_instance_get_version_check(trans));
|
|
|
|
printf(" editlevel: %x\n", qof_instance_get_editlevel(trans));
|
|
|
|
printf(" orig: %p\n", trans->orig);
|
|
|
|
printf(" idata: %x\n", qof_instance_get_idata(trans));
|
|
|
|
printf(" splits: ");
|
|
|
|
for (node = trans->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
printf("%p ", node->data);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
for (node = trans->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
xaccSplitDump(node->data, tag);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
#endif
|
2003-06-15 22:48:59 -05:00
|
|
|
|
|
|
|
void
|
|
|
|
xaccTransSortSplits (Transaction *trans)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *node, *new_list = NULL;
|
|
|
|
Split *split;
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* first debits */
|
|
|
|
for (node = trans->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
split = node->data;
|
|
|
|
if (gnc_numeric_negative_p (xaccSplitGetValue(split)))
|
|
|
|
continue;
|
2021-02-22 04:13:21 -06:00
|
|
|
new_list = g_list_prepend (new_list, split);
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* then credits */
|
|
|
|
for (node = trans->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
split = node->data;
|
|
|
|
if (!gnc_numeric_negative_p (xaccSplitGetValue(split)))
|
|
|
|
continue;
|
2021-02-22 04:13:21 -06:00
|
|
|
new_list = g_list_prepend (new_list, split);
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* install newly sorted list */
|
|
|
|
g_list_free(trans->splits);
|
2021-02-22 04:13:21 -06:00
|
|
|
trans->splits = g_list_reverse (new_list);
|
2003-06-15 22:48:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
2010-03-02 15:40:28 -06:00
|
|
|
/* This routine is not exposed externally, since it does weird things,
|
|
|
|
* like not really owning the splits correctly, and other weirdnesses.
|
|
|
|
* This routine is prone to programmer snafu if not used correctly.
|
2001-08-07 18:36:04 -05:00
|
|
|
* It is used only by the edit-rollback code.
|
|
|
|
*/
|
2014-05-07 08:37:14 -05:00
|
|
|
static Transaction *
|
|
|
|
dupe_trans (const Transaction *from)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
Transaction *to;
|
|
|
|
GList *node;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
to = g_object_new (GNC_TYPE_TRANSACTION, NULL);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2021-07-11 12:51:41 -05:00
|
|
|
CACHE_REPLACE (to->num, from->num);
|
|
|
|
CACHE_REPLACE (to->description, from->description);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
to->splits = g_list_copy (from->splits);
|
|
|
|
for (node = to->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
node->data = xaccDupeSplit (node->data);
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
to->date_entered = from->date_entered;
|
|
|
|
to->date_posted = from->date_posted;
|
|
|
|
qof_instance_copy_version(to, from);
|
|
|
|
to->orig = NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
to->common_currency = from->common_currency;
|
2001-10-17 04:25:10 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Trash the guid and entity table. We don't want to mistake
|
|
|
|
* the cloned transaction as something official. If we ever
|
|
|
|
* use this transaction, we'll have to fix this up.
|
|
|
|
*/
|
|
|
|
to->inst.e_type = NULL;
|
|
|
|
qof_instance_set_guid(to, guid_null());
|
|
|
|
qof_instance_copy_book(to, from);
|
2015-05-08 15:33:40 -05:00
|
|
|
qof_instance_copy_kvp (QOF_INSTANCE(to), QOF_INSTANCE(from));
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return to;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2013-02-28 03:52:12 -06:00
|
|
|
/********************************************************************\
|
2003-06-15 22:48:59 -05:00
|
|
|
* Use this routine to externally duplicate a transaction. It creates
|
2014-05-07 08:37:14 -05:00
|
|
|
* a full fledged transaction with unique guid, splits, etc. and
|
|
|
|
* writes it to the database.
|
2013-02-28 03:52:12 -06:00
|
|
|
\********************************************************************/
|
2003-06-15 22:48:59 -05:00
|
|
|
Transaction *
|
2014-05-07 08:37:14 -05:00
|
|
|
xaccTransCloneNoKvp (const Transaction *from)
|
2003-06-15 22:48:59 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
Transaction *to;
|
|
|
|
Split *split;
|
|
|
|
GList *node;
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_event_suspend();
|
|
|
|
to = g_object_new (GNC_TYPE_TRANSACTION, NULL);
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
to->date_entered = from->date_entered;
|
|
|
|
to->date_posted = from->date_posted;
|
2021-07-11 12:51:41 -05:00
|
|
|
CACHE_REPLACE (to->num, from->num);
|
|
|
|
CACHE_REPLACE (to->description, from->description);
|
2010-03-02 15:40:28 -06:00
|
|
|
to->common_currency = from->common_currency;
|
|
|
|
qof_instance_copy_version(to, from);
|
|
|
|
qof_instance_copy_version_check(to, from);
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
to->orig = NULL;
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2014-05-07 08:37:14 -05:00
|
|
|
qof_instance_init_data (&to->inst, GNC_ID_TRANS,
|
|
|
|
qof_instance_get_book(from));
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransBeginEdit(to);
|
|
|
|
for (node = from->splits; node; node = node->next)
|
|
|
|
{
|
2014-05-07 08:37:14 -05:00
|
|
|
split = xaccSplitCloneNoKvp(node->data);
|
2010-03-02 15:40:28 -06:00
|
|
|
split->parent = to;
|
|
|
|
to->splits = g_list_append (to->splits, split);
|
|
|
|
}
|
|
|
|
qof_instance_set_dirty(QOF_INSTANCE(to));
|
|
|
|
xaccTransCommitEdit(to);
|
|
|
|
qof_event_resume();
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return to;
|
2003-06-15 22:48:59 -05:00
|
|
|
}
|
|
|
|
|
2014-05-07 08:37:14 -05:00
|
|
|
Transaction *
|
|
|
|
xaccTransClone (const Transaction *from)
|
|
|
|
{
|
|
|
|
Transaction *to = xaccTransCloneNoKvp (from);
|
2021-06-12 15:23:36 -05:00
|
|
|
|
|
|
|
if (g_list_length (to->splits) != g_list_length (from->splits))
|
|
|
|
{
|
|
|
|
PERR ("Cloned transaction has different number of splits from original");
|
|
|
|
xaccTransDestroy (to);
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-05-07 08:37:14 -05:00
|
|
|
|
|
|
|
xaccTransBeginEdit (to);
|
2015-05-08 15:33:40 -05:00
|
|
|
qof_instance_copy_kvp (QOF_INSTANCE (to), QOF_INSTANCE (from));
|
2019-12-04 20:16:45 -06:00
|
|
|
|
2021-06-12 15:23:36 -05:00
|
|
|
for (GList* lfrom = from->splits, *lto = to->splits; lfrom && lto;
|
|
|
|
lfrom = g_list_next (lfrom), lto = g_list_next (lto))
|
2019-12-04 20:16:45 -06:00
|
|
|
xaccSplitCopyKvp (lfrom->data, lto->data);
|
|
|
|
|
2014-05-07 08:37:14 -05:00
|
|
|
xaccTransCommitEdit (to);
|
|
|
|
return to;
|
|
|
|
}
|
|
|
|
|
2013-02-28 03:52:12 -06:00
|
|
|
/*################## Added for Reg2 #################*/
|
2001-08-07 18:36:04 -05:00
|
|
|
|
|
|
|
/********************************************************************\
|
2013-02-28 03:52:12 -06:00
|
|
|
* Copy a transaction to the 'clipboard' transaction using
|
2014-05-07 08:37:14 -05:00
|
|
|
* dupe_trans. The 'clipboard' transaction must never
|
2013-02-28 03:52:12 -06:00
|
|
|
* be dereferenced.
|
2001-08-07 18:36:04 -05:00
|
|
|
\********************************************************************/
|
2013-02-28 03:52:12 -06:00
|
|
|
Transaction * xaccTransCopyToClipBoard(const Transaction *from_trans)
|
|
|
|
{
|
|
|
|
Transaction *to_trans;
|
|
|
|
|
|
|
|
if (!from_trans)
|
|
|
|
return NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2014-05-07 08:37:14 -05:00
|
|
|
to_trans = dupe_trans(from_trans);
|
2013-02-28 03:52:12 -06:00
|
|
|
return to_trans;
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************\
|
|
|
|
* Copy a transaction to another using the function below without
|
|
|
|
* changing any account information.
|
|
|
|
\********************************************************************/
|
|
|
|
void
|
|
|
|
xaccTransCopyOnto(const Transaction *from_trans, Transaction *to_trans)
|
|
|
|
{
|
2013-03-11 13:08:08 -05:00
|
|
|
xaccTransCopyFromClipBoard(from_trans, to_trans, NULL, NULL, TRUE);
|
2013-02-28 03:52:12 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************\
|
|
|
|
* This function explicitly must robustly handle some unusual input.
|
|
|
|
*
|
2014-05-07 08:37:14 -05:00
|
|
|
* 'from_trans' may be a duped trans (see dupe_trans), so its
|
2013-02-28 03:52:12 -06:00
|
|
|
* splits may not really belong to the accounts that they say they do.
|
|
|
|
*
|
|
|
|
* 'from_acc' need not be a valid account. It may be an already freed
|
|
|
|
* Account. Therefore, it must not be dereferenced at all.
|
|
|
|
*
|
2013-03-11 13:08:08 -05:00
|
|
|
* Neither 'from_trans', nor 'from_acc', nor any of 'from's splits may
|
|
|
|
* be modified in any way.
|
|
|
|
*
|
2013-05-18 09:23:12 -05:00
|
|
|
* 'no_date' if TRUE will not copy the date posted.
|
2013-02-28 03:52:12 -06:00
|
|
|
*
|
|
|
|
* The 'to_trans' transaction will end up with valid copies of from's
|
|
|
|
* splits. In addition, the copies of any of from's splits that were
|
|
|
|
* in from_acc (or at least claimed to be) will end up in to_acc.
|
|
|
|
\********************************************************************/
|
|
|
|
void
|
|
|
|
xaccTransCopyFromClipBoard(const Transaction *from_trans, Transaction *to_trans,
|
2013-05-18 09:23:12 -05:00
|
|
|
const Account *from_acc, Account *to_acc, gboolean no_date)
|
2013-02-28 03:52:12 -06:00
|
|
|
{
|
|
|
|
gboolean change_accounts = FALSE;
|
|
|
|
GList *node;
|
|
|
|
|
|
|
|
if (!from_trans || !to_trans)
|
|
|
|
return;
|
|
|
|
|
|
|
|
change_accounts = from_acc && GNC_IS_ACCOUNT(to_acc) && from_acc != to_acc;
|
|
|
|
xaccTransBeginEdit(to_trans);
|
|
|
|
|
|
|
|
FOR_EACH_SPLIT(to_trans, xaccSplitDestroy(s));
|
2016-03-17 17:37:19 -05:00
|
|
|
g_list_free(to_trans->splits);
|
|
|
|
to_trans->splits = NULL;
|
2013-02-28 03:52:12 -06:00
|
|
|
|
|
|
|
xaccTransSetCurrency(to_trans, xaccTransGetCurrency(from_trans));
|
|
|
|
xaccTransSetDescription(to_trans, xaccTransGetDescription(from_trans));
|
2013-04-20 11:45:56 -05:00
|
|
|
|
2013-05-18 09:23:12 -05:00
|
|
|
if ((xaccTransGetNum(to_trans) == NULL) || (g_strcmp0 (xaccTransGetNum(to_trans), "") == 0))
|
|
|
|
xaccTransSetNum(to_trans, xaccTransGetNum(from_trans));
|
|
|
|
|
2013-02-28 03:52:12 -06:00
|
|
|
xaccTransSetNotes(to_trans, xaccTransGetNotes(from_trans));
|
2020-08-15 19:05:21 -05:00
|
|
|
xaccTransSetDocLink(to_trans, xaccTransGetDocLink (from_trans));
|
2013-05-18 09:23:12 -05:00
|
|
|
if(!no_date)
|
2013-03-11 13:08:08 -05:00
|
|
|
{
|
2017-12-31 06:37:02 -06:00
|
|
|
xaccTransSetDatePostedSecs(to_trans, xaccTransRetDatePosted (from_trans));
|
2013-03-11 13:08:08 -05:00
|
|
|
}
|
2013-02-28 03:52:12 -06:00
|
|
|
|
|
|
|
/* Each new split will be parented to 'to' */
|
|
|
|
for (node = from_trans->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
Split *new_split = xaccMallocSplit( qof_instance_get_book(QOF_INSTANCE(from_trans)));
|
|
|
|
xaccSplitCopyOnto(node->data, new_split);
|
|
|
|
if (change_accounts && xaccSplitGetAccount(node->data) == from_acc)
|
|
|
|
xaccSplitSetAccount(new_split, to_acc);
|
|
|
|
xaccSplitSetParent(new_split, to_trans);
|
|
|
|
}
|
|
|
|
xaccTransCommitEdit(to_trans);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*################## Added for Reg2 #################*/
|
|
|
|
|
|
|
|
/********************************************************************\
|
|
|
|
Free the transaction.
|
|
|
|
\********************************************************************/
|
2001-08-07 18:36:04 -05:00
|
|
|
static void
|
|
|
|
xaccFreeTransaction (Transaction *trans)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *node;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans) return;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER ("(addr=%p)", trans);
|
|
|
|
if (((char *) 1) == trans->num)
|
|
|
|
{
|
|
|
|
PERR ("double-free %p", trans);
|
|
|
|
LEAVE (" ");
|
|
|
|
return;
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* free up the destination splits */
|
|
|
|
for (node = trans->splits; node; node = node->next)
|
|
|
|
xaccFreeSplit (node->data);
|
|
|
|
g_list_free (trans->splits);
|
|
|
|
trans->splits = NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* free up transaction strings */
|
|
|
|
CACHE_REMOVE(trans->num);
|
|
|
|
CACHE_REMOVE(trans->description);
|
2018-09-09 17:02:53 -05:00
|
|
|
g_free (trans->readonly_reason);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
/* Just in case someone looks up freed memory ... */
|
|
|
|
trans->num = (char *) 1;
|
|
|
|
trans->description = NULL;
|
2017-12-31 06:37:02 -06:00
|
|
|
trans->date_entered = 0;
|
|
|
|
trans->date_posted = 0;
|
2018-09-09 15:49:52 -05:00
|
|
|
trans->readonly_reason = NULL;
|
|
|
|
trans->reason_cache_valid = FALSE;
|
2010-03-02 15:40:28 -06:00
|
|
|
if (trans->orig)
|
|
|
|
{
|
|
|
|
xaccFreeTransaction (trans->orig);
|
|
|
|
trans->orig = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* qof_instance_release (&trans->inst); */
|
|
|
|
g_object_unref(trans);
|
|
|
|
|
|
|
|
LEAVE ("(addr=%p)", trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
xaccTransEqual
|
|
|
|
|
|
|
|
Compare two transactions for equality. We don't pay any attention to
|
|
|
|
rollback issues here, and we only care about equality of "permanent
|
|
|
|
fields", basically the things that would survive a file save/load
|
|
|
|
cycle.
|
|
|
|
|
|
|
|
********************************************************************/
|
|
|
|
|
2001-11-07 04:45:59 -06:00
|
|
|
/* return 0 when splits have equal guids */
|
|
|
|
static gint
|
|
|
|
compare_split_guids (gconstpointer a, gconstpointer b)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
const Split *sa = a;
|
|
|
|
const Split *sb = b;
|
2001-11-07 04:45:59 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (sa == sb) return 0;
|
|
|
|
if (!sa || !sb) return 1;
|
2001-11-07 04:45:59 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return guid_compare (xaccSplitGetGUID (sa), xaccSplitGetGUID (sb));
|
2001-11-07 04:45:59 -06:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
gboolean
|
|
|
|
xaccTransEqual(const Transaction *ta, const Transaction *tb,
|
|
|
|
gboolean check_guids,
|
2003-06-15 22:48:59 -05:00
|
|
|
gboolean check_splits,
|
|
|
|
gboolean check_balances,
|
|
|
|
gboolean assume_ordered)
|
|
|
|
{
|
2010-03-25 13:32:40 -05:00
|
|
|
gboolean same_book;
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!ta && !tb) return TRUE; /* Arguable. FALSE may be better. */
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!ta || !tb)
|
|
|
|
{
|
2013-06-25 12:04:47 -05:00
|
|
|
PINFO ("one is NULL");
|
2010-03-02 15:40:28 -06:00
|
|
|
return FALSE;
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (ta == tb) return TRUE;
|
2003-10-16 23:25:53 -05:00
|
|
|
|
2010-03-25 13:32:40 -05:00
|
|
|
same_book = qof_instance_get_book(QOF_INSTANCE(ta)) == qof_instance_get_book(QOF_INSTANCE(tb));
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (check_guids)
|
2001-10-11 03:22:44 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (qof_instance_guid_compare(ta, tb) != 0)
|
|
|
|
{
|
2013-06-13 15:42:46 -05:00
|
|
|
PINFO ("GUIDs differ");
|
2010-03-02 15:40:28 -06:00
|
|
|
return FALSE;
|
|
|
|
}
|
2001-10-11 03:22:44 -05:00
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!gnc_commodity_equal(ta->common_currency, tb->common_currency))
|
|
|
|
{
|
2013-06-25 12:04:47 -05:00
|
|
|
PINFO ("commodities differ %s vs %s",
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_get_unique_name (ta->common_currency),
|
|
|
|
gnc_commodity_get_unique_name (tb->common_currency));
|
|
|
|
return FALSE;
|
|
|
|
}
|
2001-10-11 03:22:44 -05:00
|
|
|
|
2017-12-31 06:37:02 -06:00
|
|
|
if (ta->date_entered != tb->date_entered)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2010-03-25 13:32:40 -05:00
|
|
|
char buf1[100];
|
|
|
|
char buf2[100];
|
|
|
|
|
2017-12-31 06:37:02 -06:00
|
|
|
(void)gnc_time64_to_iso8601_buff(ta->date_entered, buf1);
|
|
|
|
(void)gnc_time64_to_iso8601_buff(tb->date_entered, buf2);
|
2013-06-25 12:04:47 -05:00
|
|
|
PINFO ("date entered differs: '%s' vs '%s'", buf1, buf2);
|
2010-03-02 15:40:28 -06:00
|
|
|
return FALSE;
|
|
|
|
}
|
2001-10-11 03:22:44 -05:00
|
|
|
|
2017-12-31 06:37:02 -06:00
|
|
|
if (ta->date_posted != tb->date_posted)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2010-03-25 13:32:40 -05:00
|
|
|
char buf1[100];
|
|
|
|
char buf2[100];
|
|
|
|
|
2017-12-31 06:37:02 -06:00
|
|
|
(void)gnc_time64_to_iso8601_buff(ta->date_posted, buf1);
|
|
|
|
(void)gnc_time64_to_iso8601_buff(tb->date_posted, buf2);
|
2013-06-25 12:04:47 -05:00
|
|
|
PINFO ("date posted differs: '%s' vs '%s'", buf1, buf2);
|
2010-03-02 15:40:28 -06:00
|
|
|
return FALSE;
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-25 13:32:40 -05:00
|
|
|
/* If the same book, since we use cached strings, we can just compare pointer
|
2010-03-02 15:40:28 -06:00
|
|
|
* equality for num and description
|
|
|
|
*/
|
2012-08-07 12:24:55 -05:00
|
|
|
if ((same_book && ta->num != tb->num) || (!same_book && g_strcmp0(ta->num, tb->num) != 0))
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2013-06-25 12:04:47 -05:00
|
|
|
PINFO ("num differs: %s vs %s", ta->num, tb->num);
|
2010-03-02 15:40:28 -06:00
|
|
|
return FALSE;
|
|
|
|
}
|
2001-10-11 03:22:44 -05:00
|
|
|
|
2010-03-25 13:32:40 -05:00
|
|
|
if ((same_book && ta->description != tb->description)
|
2012-08-07 12:24:55 -05:00
|
|
|
|| (!same_book && g_strcmp0(ta->description, tb->description)))
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2013-06-25 12:04:47 -05:00
|
|
|
PINFO ("descriptions differ: %s vs %s", ta->description, tb->description);
|
2010-03-02 15:40:28 -06:00
|
|
|
return FALSE;
|
|
|
|
}
|
2001-10-11 03:22:44 -05:00
|
|
|
|
2015-05-08 15:33:40 -05:00
|
|
|
if (qof_instance_compare_kvp (QOF_INSTANCE (ta), QOF_INSTANCE (tb)) != 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
char *frame_a;
|
|
|
|
char *frame_b;
|
2001-10-11 03:22:44 -05:00
|
|
|
|
2015-05-08 15:33:40 -05:00
|
|
|
frame_a = qof_instance_kvp_as_string (QOF_INSTANCE (ta));
|
|
|
|
frame_b = qof_instance_kvp_as_string (QOF_INSTANCE (tb));
|
|
|
|
|
2001-10-11 03:22:44 -05:00
|
|
|
|
2013-06-25 12:04:47 -05:00
|
|
|
PINFO ("kvp frames differ:\n%s\n\nvs\n\n%s", frame_a, frame_b);
|
2001-10-11 03:22:44 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_free (frame_a);
|
|
|
|
g_free (frame_b);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return FALSE;
|
2001-10-11 03:22:44 -05:00
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (check_splits)
|
2001-10-11 03:22:44 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if ((!ta->splits && tb->splits) || (!tb->splits && ta->splits))
|
2001-11-07 04:45:59 -06:00
|
|
|
{
|
2013-06-25 12:04:47 -05:00
|
|
|
PINFO ("only one has splits");
|
2010-03-02 15:40:28 -06:00
|
|
|
return FALSE;
|
2001-11-07 04:45:59 -06:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (ta->splits && tb->splits)
|
2001-10-11 03:22:44 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *node_a, *node_b;
|
|
|
|
|
|
|
|
for (node_a = ta->splits, node_b = tb->splits;
|
|
|
|
node_a;
|
|
|
|
node_a = node_a->next, node_b = node_b->next)
|
|
|
|
{
|
|
|
|
Split *split_a = node_a->data;
|
|
|
|
Split *split_b;
|
|
|
|
|
|
|
|
/* don't presume that the splits are in the same order */
|
|
|
|
if (!assume_ordered)
|
|
|
|
node_b = g_list_find_custom (tb->splits, split_a,
|
|
|
|
compare_split_guids);
|
|
|
|
|
|
|
|
if (!node_b)
|
|
|
|
{
|
2014-07-25 16:02:44 -05:00
|
|
|
gchar guidstr[GUID_ENCODING_LENGTH+1];
|
|
|
|
guid_to_string_buff (xaccSplitGetGUID (split_a),guidstr);
|
|
|
|
|
|
|
|
PINFO ("first has split %s and second does not",guidstr);
|
2010-03-02 15:40:28 -06:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
split_b = node_b->data;
|
|
|
|
|
|
|
|
if (!xaccSplitEqual (split_a, split_b, check_guids, check_balances,
|
|
|
|
FALSE))
|
|
|
|
{
|
2011-07-17 12:35:30 -05:00
|
|
|
char str_a[GUID_ENCODING_LENGTH + 1];
|
|
|
|
char str_b[GUID_ENCODING_LENGTH + 1];
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
guid_to_string_buff (xaccSplitGetGUID (split_a), str_a);
|
|
|
|
guid_to_string_buff (xaccSplitGetGUID (split_b), str_b);
|
|
|
|
|
2013-06-25 12:04:47 -05:00
|
|
|
PINFO ("splits %s and %s differ", str_a, str_b);
|
2010-03-02 15:40:28 -06:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_list_length (ta->splits) != g_list_length (tb->splits))
|
|
|
|
{
|
2013-06-25 12:04:47 -05:00
|
|
|
PINFO ("different number of splits");
|
2010-03-02 15:40:28 -06:00
|
|
|
return FALSE;
|
|
|
|
}
|
2001-10-11 03:22:44 -05:00
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return TRUE;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
/********************************************************************\
|
|
|
|
xaccTransUseTradingAccounts
|
|
|
|
|
|
|
|
Returns true if the transaction should include trading account splits if
|
|
|
|
it involves more than one commodity.
|
|
|
|
\********************************************************************/
|
|
|
|
|
|
|
|
gboolean xaccTransUseTradingAccounts(const Transaction *trans)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
return qof_book_use_trading_accounts(qof_instance_get_book (trans));
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
|
|
|
|
2001-10-08 02:14:58 -05:00
|
|
|
Transaction *
|
2010-03-27 16:01:21 -05:00
|
|
|
xaccTransLookup (const GncGUID *guid, QofBook *book)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
QofCollection *col;
|
|
|
|
if (!guid || !book) return NULL;
|
|
|
|
col = qof_book_get_collection (book, GNC_ID_TRANS);
|
|
|
|
return (Transaction *) qof_collection_lookup_entity (col, guid);
|
2002-01-12 21:05:26 -06:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
|
|
|
|
|
|
|
gnc_numeric
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
xaccTransGetImbalanceValue (const Transaction * trans)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_numeric imbal = gnc_numeric_zero();
|
|
|
|
if (!trans) return imbal;
|
2004-07-05 22:36:47 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER("(trans=%p)", trans);
|
|
|
|
/* Could use xaccSplitsComputeValue, except that we want to use
|
|
|
|
GNC_HOW_DENOM_EXACT */
|
|
|
|
FOR_EACH_SPLIT(trans, imbal =
|
|
|
|
gnc_numeric_add(imbal, xaccSplitGetValue(s),
|
|
|
|
GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT));
|
|
|
|
LEAVE("(trans=%p) imbal=%s", trans, gnc_num_dbg_to_string(imbal));
|
|
|
|
return imbal;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
MonetaryList *
|
|
|
|
xaccTransGetImbalance (const Transaction * trans)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
/* imbal_value is used if either (1) the transaction has a non currency
|
|
|
|
split or (2) all the splits are in the same currency. If there are
|
|
|
|
no non-currency splits and not all splits are in the same currency then
|
|
|
|
imbal_list is used to compute the imbalance. */
|
|
|
|
MonetaryList *imbal_list = NULL;
|
|
|
|
gnc_numeric imbal_value = gnc_numeric_zero();
|
|
|
|
gboolean trading_accts;
|
|
|
|
|
|
|
|
if (!trans) return imbal_list;
|
|
|
|
|
|
|
|
ENTER("(trans=%p)", trans);
|
|
|
|
|
|
|
|
trading_accts = xaccTransUseTradingAccounts (trans);
|
|
|
|
|
|
|
|
/* If using trading accounts and there is at least one split that is not
|
|
|
|
in the transaction currency or a split that has a price or exchange
|
|
|
|
rate other than 1, then compute the balance in each commodity in the
|
|
|
|
transaction. Otherwise (all splits are in the transaction's currency)
|
|
|
|
then compute the balance using the value fields.
|
|
|
|
|
|
|
|
Optimize for the common case of only one currency and a balanced
|
|
|
|
transaction. */
|
|
|
|
FOR_EACH_SPLIT(trans,
|
|
|
|
{
|
|
|
|
gnc_commodity *commodity;
|
|
|
|
commodity = xaccAccountGetCommodity(xaccSplitGetAccount(s));
|
|
|
|
if (trading_accts &&
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
(imbal_list ||
|
2010-03-02 15:40:28 -06:00
|
|
|
! gnc_commodity_equiv(commodity, trans->common_currency) ||
|
|
|
|
! gnc_numeric_equal(xaccSplitGetAmount(s), xaccSplitGetValue(s))))
|
|
|
|
{
|
|
|
|
/* Need to use (or already are using) a list of imbalances in each of
|
|
|
|
the currencies used in the transaction. */
|
|
|
|
if (! imbal_list)
|
|
|
|
{
|
|
|
|
/* All previous splits have been in the transaction's common
|
|
|
|
currency, so imbal_value is in this currency. */
|
|
|
|
imbal_list = gnc_monetary_list_add_value(imbal_list,
|
|
|
|
trans->common_currency,
|
|
|
|
imbal_value);
|
|
|
|
}
|
|
|
|
imbal_list = gnc_monetary_list_add_value(imbal_list, commodity,
|
2011-07-17 12:35:30 -05:00
|
|
|
xaccSplitGetAmount(s));
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Add it to the value accumulator in case we need it. */
|
|
|
|
imbal_value = gnc_numeric_add(imbal_value, xaccSplitGetValue(s),
|
2011-07-17 12:35:30 -05:00
|
|
|
GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
|
2010-03-02 15:40:28 -06:00
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
|
|
if (!imbal_list && !gnc_numeric_zero_p(imbal_value))
|
|
|
|
{
|
|
|
|
/* Not balanced and no list, create one. If we found multiple currencies
|
|
|
|
and no non-currency commodity then imbal_list will already exist and
|
|
|
|
we won't get here. */
|
|
|
|
imbal_list = gnc_monetary_list_add_value(imbal_list,
|
|
|
|
trans->common_currency,
|
|
|
|
imbal_value);
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
/* Delete all the zero entries from the list, perhaps leaving an
|
|
|
|
empty list */
|
|
|
|
imbal_list = gnc_monetary_list_delete_zeros(imbal_list);
|
|
|
|
|
|
|
|
LEAVE("(trans=%p), imbal=%p", trans, imbal_list);
|
|
|
|
return imbal_list;
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
xaccTransIsBalanced (const Transaction *trans)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
MonetaryList *imbal_list;
|
|
|
|
gboolean result;
|
2012-12-12 23:13:42 -06:00
|
|
|
gnc_numeric imbal = gnc_numeric_zero();
|
|
|
|
gnc_numeric imbal_trading = gnc_numeric_zero();
|
2013-08-16 11:43:39 -05:00
|
|
|
|
|
|
|
if (trans == NULL) return FALSE;
|
|
|
|
|
2012-12-12 23:13:42 -06:00
|
|
|
if (xaccTransUseTradingAccounts(trans))
|
|
|
|
{
|
2016-02-16 19:11:55 -06:00
|
|
|
/* Transaction is imbalanced if the value is imbalanced in either
|
2012-12-12 23:13:42 -06:00
|
|
|
trading or non-trading splits. One can't be used to balance
|
|
|
|
the other. */
|
2016-02-16 19:11:55 -06:00
|
|
|
FOR_EACH_SPLIT(trans,
|
2012-12-12 23:13:42 -06:00
|
|
|
{
|
2013-12-07 01:33:24 -06:00
|
|
|
Account *acc = xaccSplitGetAccount(s);
|
|
|
|
if (!acc || xaccAccountGetType(acc) != ACCT_TYPE_TRADING)
|
2012-12-12 23:13:42 -06:00
|
|
|
{
|
|
|
|
imbal = gnc_numeric_add(imbal, xaccSplitGetValue(s),
|
|
|
|
GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
imbal_trading = gnc_numeric_add(imbal_trading, xaccSplitGetValue(s),
|
|
|
|
GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
|
|
|
|
}
|
2016-02-16 19:11:55 -06:00
|
|
|
}
|
2012-12-12 23:13:42 -06:00
|
|
|
);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
imbal = xaccTransGetImbalanceValue(trans);
|
2016-02-16 19:11:55 -06:00
|
|
|
|
2012-12-12 23:13:42 -06:00
|
|
|
if (! gnc_numeric_zero_p(imbal) || ! gnc_numeric_zero_p(imbal_trading))
|
2010-03-02 15:40:28 -06:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!xaccTransUseTradingAccounts (trans))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
imbal_list = xaccTransGetImbalance(trans);
|
|
|
|
result = imbal_list == NULL;
|
|
|
|
gnc_monetary_list_free(imbal_list);
|
|
|
|
return result;
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
|
|
|
|
2002-06-26 21:11:17 -05:00
|
|
|
gnc_numeric
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransGetAccountValue (const Transaction *trans,
|
2006-03-03 18:10:12 -06:00
|
|
|
const Account *acc)
|
2002-06-26 21:11:17 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_numeric total = gnc_numeric_zero ();
|
|
|
|
if (!trans || !acc) return total;
|
2002-06-26 21:11:17 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
FOR_EACH_SPLIT(trans, if (acc == xaccSplitGetAccount(s))
|
|
|
|
{
|
|
|
|
total = gnc_numeric_add (total, xaccSplitGetValue (s),
|
|
|
|
GNC_DENOM_AUTO,
|
|
|
|
GNC_HOW_DENOM_EXACT);
|
|
|
|
});
|
|
|
|
return total;
|
2002-06-26 21:11:17 -05:00
|
|
|
}
|
|
|
|
|
2006-01-29 20:59:43 -06:00
|
|
|
gnc_numeric
|
2006-03-03 18:10:12 -06:00
|
|
|
xaccTransGetAccountAmount (const Transaction *trans, const Account *acc)
|
2006-01-29 20:59:43 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_numeric total = gnc_numeric_zero ();
|
|
|
|
if (!trans || !acc) return total;
|
2006-01-29 20:59:43 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
total = gnc_numeric_convert (total, xaccAccountGetCommoditySCU (acc),
|
2010-10-23 05:38:48 -05:00
|
|
|
GNC_HOW_RND_ROUND_HALF_UP);
|
2010-03-02 15:40:28 -06:00
|
|
|
FOR_EACH_SPLIT(trans, if (acc == xaccSplitGetAccount(s))
|
|
|
|
total = gnc_numeric_add_fixed(
|
|
|
|
total, xaccSplitGetAmount(s)));
|
|
|
|
return total;
|
2006-01-29 20:59:43 -06:00
|
|
|
}
|
|
|
|
|
2012-10-18 03:15:21 -05:00
|
|
|
/*################## Added for Reg2 #################*/
|
2012-08-07 12:24:33 -05:00
|
|
|
gboolean
|
|
|
|
xaccTransGetRateForCommodity(const Transaction *trans,
|
|
|
|
const gnc_commodity *split_com,
|
2013-02-28 03:52:12 -06:00
|
|
|
const Split *split, gnc_numeric *rate)
|
2012-08-07 12:24:33 -05:00
|
|
|
{
|
|
|
|
GList *splits;
|
|
|
|
gnc_commodity *trans_curr;
|
|
|
|
|
2013-08-16 11:43:12 -05:00
|
|
|
if (trans == NULL || split_com == NULL || split == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
2013-02-28 03:52:12 -06:00
|
|
|
trans_curr = xaccTransGetCurrency (trans);
|
|
|
|
if (gnc_commodity_equal (trans_curr, split_com))
|
|
|
|
{
|
2013-03-11 13:08:08 -05:00
|
|
|
if (rate)
|
2013-02-28 03:52:12 -06:00
|
|
|
*rate = gnc_numeric_create (1, 1);
|
2012-08-07 12:24:33 -05:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2013-02-28 03:52:12 -06:00
|
|
|
for (splits = trans->splits; splits; splits = splits->next)
|
|
|
|
{
|
2012-08-07 12:24:33 -05:00
|
|
|
Split *s = splits->data;
|
|
|
|
gnc_commodity *comm;
|
|
|
|
|
2013-02-28 03:52:12 -06:00
|
|
|
if (!xaccTransStillHasSplit (trans, s)) continue;
|
2012-08-07 12:24:33 -05:00
|
|
|
|
2013-02-28 03:52:12 -06:00
|
|
|
if (s == split)
|
|
|
|
{
|
|
|
|
comm = xaccAccountGetCommodity (xaccSplitGetAccount(s));
|
|
|
|
if (gnc_commodity_equal (split_com, comm))
|
|
|
|
{
|
|
|
|
gnc_numeric amt = xaccSplitGetAmount (s);
|
|
|
|
gnc_numeric val = xaccSplitGetValue (s);
|
2012-08-07 12:24:33 -05:00
|
|
|
|
2013-02-28 03:52:12 -06:00
|
|
|
if (!gnc_numeric_zero_p (xaccSplitGetAmount (s)) &&
|
|
|
|
!gnc_numeric_zero_p (xaccSplitGetValue (s)))
|
|
|
|
{
|
|
|
|
if (rate)
|
|
|
|
*rate = gnc_numeric_div (amt, val, GNC_DENOM_AUTO,
|
|
|
|
GNC_HOW_DENOM_REDUCE);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2012-08-07 12:24:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
2012-10-18 03:15:21 -05:00
|
|
|
/*################## Added for Reg2 #################*/
|
2012-08-07 12:24:33 -05:00
|
|
|
|
2006-01-29 20:59:43 -06:00
|
|
|
gnc_numeric
|
2010-03-07 15:28:15 -06:00
|
|
|
xaccTransGetAccountConvRate(const Transaction *txn, const Account *acc)
|
2006-01-29 20:59:43 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_numeric amount, value, convrate;
|
|
|
|
GList *splits;
|
|
|
|
Split *s;
|
|
|
|
gboolean found_acc_match = FALSE;
|
|
|
|
gnc_commodity *acc_commod = xaccAccountGetCommodity(acc);
|
|
|
|
|
|
|
|
/* We need to compute the conversion rate into _this account_. So,
|
|
|
|
* find the first split into this account, compute the conversion
|
|
|
|
* rate (based on amount/value), and then return this conversion
|
|
|
|
* rate.
|
2006-01-29 20:59:43 -06:00
|
|
|
*/
|
2010-03-02 15:40:28 -06:00
|
|
|
if (gnc_commodity_equal(acc_commod, xaccTransGetCurrency(txn)))
|
|
|
|
return gnc_numeric_create(1, 1);
|
|
|
|
|
|
|
|
for (splits = txn->splits; splits; splits = splits->next)
|
|
|
|
{
|
|
|
|
Account *split_acc;
|
|
|
|
gnc_commodity *split_commod;
|
|
|
|
|
|
|
|
s = splits->data;
|
|
|
|
|
|
|
|
if (!xaccTransStillHasSplit(txn, s))
|
|
|
|
continue;
|
|
|
|
split_acc = xaccSplitGetAccount (s);
|
|
|
|
split_commod = xaccAccountGetCommodity (split_acc);
|
|
|
|
if (! (split_acc == acc ||
|
|
|
|
gnc_commodity_equal (split_commod, acc_commod)))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
found_acc_match = TRUE;
|
|
|
|
amount = xaccSplitGetAmount (s);
|
|
|
|
|
|
|
|
/* Ignore splits with "zero" amount */
|
|
|
|
if (gnc_numeric_zero_p (amount))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
value = xaccSplitGetValue (s);
|
|
|
|
if (gnc_numeric_zero_p (value))
|
|
|
|
PWARN("How can amount be nonzero and value be zero?");
|
|
|
|
|
2010-08-26 12:22:06 -05:00
|
|
|
convrate = gnc_numeric_div(amount, value, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
|
2010-03-02 15:40:28 -06:00
|
|
|
return convrate;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (acc)
|
|
|
|
{
|
|
|
|
/* If we did find a matching account but its amount was zero,
|
|
|
|
* then perhaps this is a "special" income/loss transaction
|
|
|
|
*/
|
|
|
|
if (found_acc_match)
|
|
|
|
return gnc_numeric_zero();
|
|
|
|
else
|
|
|
|
PERR("Cannot convert transaction -- no splits with proper conversion ratio");
|
|
|
|
}
|
|
|
|
return gnc_numeric_create (100, 100);
|
2006-01-29 20:59:43 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
gnc_numeric
|
|
|
|
xaccTransGetAccountBalance (const Transaction *trans,
|
|
|
|
const Account *account)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *node;
|
|
|
|
Split *last_split = NULL;
|
|
|
|
|
|
|
|
// Not really the appropriate error value.
|
|
|
|
g_return_val_if_fail(account && trans, gnc_numeric_error(GNC_ERROR_ARG));
|
2006-01-29 20:59:43 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
for (node = trans->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
Split *split = node->data;
|
2006-01-29 20:59:43 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!xaccTransStillHasSplit(trans, split))
|
|
|
|
continue;
|
|
|
|
if (xaccSplitGetAccount(split) != account)
|
|
|
|
continue;
|
2006-01-29 20:59:43 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!last_split)
|
|
|
|
{
|
|
|
|
last_split = split;
|
|
|
|
continue;
|
|
|
|
}
|
2006-01-29 20:59:43 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* This test needs to correspond to the comparison function used when
|
|
|
|
sorting the splits for computing the running balance. */
|
|
|
|
if (xaccSplitOrder (last_split, split) < 0)
|
|
|
|
last_split = split;
|
2006-01-29 20:59:43 -06:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return xaccSplitGetBalance (last_split);
|
2006-01-29 20:59:43 -06:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
|
|
|
/* The new routine for setting the common currency */
|
|
|
|
|
|
|
|
gnc_commodity *
|
2002-12-07 07:05:45 -06:00
|
|
|
xaccTransGetCurrency (const Transaction *trans)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
return trans ? trans->common_currency : NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2016-03-17 17:37:19 -05:00
|
|
|
/* Helper functions for xaccTransSetCurrency */
|
|
|
|
static gnc_numeric
|
|
|
|
find_new_rate(Transaction *trans, gnc_commodity *curr)
|
|
|
|
{
|
|
|
|
GList *node;
|
|
|
|
gnc_numeric rate = gnc_numeric_zero();
|
|
|
|
for (node = trans->splits; node != NULL; node = g_list_next (node))
|
|
|
|
{
|
|
|
|
Split *split = GNC_SPLIT(node->data);
|
|
|
|
gnc_commodity *split_com =
|
|
|
|
xaccAccountGetCommodity(xaccSplitGetAccount(split));
|
|
|
|
if (gnc_commodity_equal(curr, split_com))
|
|
|
|
{
|
|
|
|
/* This looks backwards, but the amount of the balancing transaction
|
|
|
|
* that we're going to use it on is in the value's currency. */
|
|
|
|
rate = gnc_numeric_div(xaccSplitGetAmount(split),
|
|
|
|
xaccSplitGetValue(split),
|
|
|
|
GNC_DENOM_AUTO, GNC_HOW_RND_NEVER);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rate;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
split_set_new_value(Split* split, gnc_commodity *curr, gnc_commodity *old_curr,
|
|
|
|
gnc_numeric rate)
|
|
|
|
{
|
|
|
|
gnc_commodity *split_com =
|
|
|
|
xaccAccountGetCommodity(xaccSplitGetAccount(split));
|
|
|
|
if (gnc_commodity_equal(curr, split_com))
|
|
|
|
xaccSplitSetValue(split, xaccSplitGetAmount(split));
|
|
|
|
else if (gnc_commodity_equal(old_curr, split_com))
|
|
|
|
xaccSplitSetSharePrice(split, rate);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gnc_numeric old_rate = gnc_numeric_div(xaccSplitGetValue(split),
|
|
|
|
xaccSplitGetAmount(split),
|
|
|
|
GNC_DENOM_AUTO,
|
|
|
|
GNC_HOW_RND_NEVER);
|
|
|
|
gnc_numeric new_rate = gnc_numeric_div(old_rate, rate, GNC_DENOM_AUTO,
|
|
|
|
GNC_HOW_RND_NEVER);
|
|
|
|
xaccSplitSetSharePrice(split, new_rate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set a new currency on a transaction.
|
|
|
|
* When we do that to a transaction with splits we need to re-value
|
|
|
|
* all of the splits in the new currency.
|
|
|
|
* @param trans: The transaction to change
|
|
|
|
* @param curr: The new currency to set.
|
|
|
|
*/
|
2001-08-07 18:36:04 -05:00
|
|
|
void
|
|
|
|
xaccTransSetCurrency (Transaction *trans, gnc_commodity *curr)
|
|
|
|
{
|
2016-03-17 17:37:19 -05:00
|
|
|
gnc_commodity *old_curr = trans->common_currency;
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans || !curr || trans->common_currency == curr) return;
|
|
|
|
xaccTransBeginEdit(trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
trans->common_currency = curr;
|
2016-03-17 17:37:19 -05:00
|
|
|
if (old_curr != NULL && trans->splits != NULL)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2016-03-17 17:37:19 -05:00
|
|
|
gnc_numeric rate = find_new_rate(trans, curr);
|
|
|
|
if (!gnc_numeric_zero_p (rate))
|
|
|
|
{
|
|
|
|
FOR_EACH_SPLIT(trans, split_set_new_value(s, curr, old_curr, rate));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FOR_EACH_SPLIT(trans, xaccSplitSetValue(s, xaccSplitGetValue(s)));
|
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_instance_set_dirty(QOF_INSTANCE(trans));
|
|
|
|
mark_trans(trans); /* Dirty balance of every account in trans */
|
|
|
|
xaccTransCommitEdit(trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
|
|
|
|
|
|
|
void
|
|
|
|
xaccTransBeginEdit (Transaction *trans)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans) return;
|
|
|
|
if (!qof_begin_edit(&trans->inst)) return;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (qof_book_shutting_down(qof_instance_get_book(trans))) return;
|
2004-05-29 12:45:56 -05:00
|
|
|
|
2011-11-14 15:28:32 -06:00
|
|
|
if (!qof_book_is_readonly(qof_instance_get_book(trans)))
|
|
|
|
{
|
|
|
|
xaccOpenLog ();
|
|
|
|
xaccTransWriteLog (trans, 'B');
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Make a clone of the transaction; we will use this
|
|
|
|
* in case we need to roll-back the edit. */
|
2014-05-07 08:37:14 -05:00
|
|
|
trans->orig = dupe_trans (trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2003-09-03 08:02:37 -05:00
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
|
|
|
|
|
|
|
void
|
|
|
|
xaccTransDestroy (Transaction *trans)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans) return;
|
2003-09-03 08:02:37 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!xaccTransGetReadOnly (trans) ||
|
|
|
|
qof_book_shutting_down(qof_instance_get_book(trans)))
|
|
|
|
{
|
|
|
|
xaccTransBeginEdit(trans);
|
|
|
|
qof_instance_set_destroying(trans, TRUE);
|
|
|
|
xaccTransCommitEdit(trans);
|
|
|
|
}
|
2003-09-03 08:02:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
destroy_gains (Transaction *trans)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
SplitList *node;
|
|
|
|
for (node = trans->splits; node; node = node->next)
|
2003-09-03 08:02:37 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
Split *s = node->data;
|
|
|
|
if (!xaccTransStillHasSplit(trans, s))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (GAINS_STATUS_UNKNOWN == s->gains) xaccSplitDetermineGainStatus(s);
|
|
|
|
if (s->gains_split && (GAINS_STATUS_GAINS & s->gains_split->gains))
|
|
|
|
{
|
|
|
|
Transaction *t = s->gains_split->parent;
|
|
|
|
xaccTransDestroy (t);
|
|
|
|
s->gains_split = NULL;
|
|
|
|
}
|
2003-09-03 08:02:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
do_destroy (Transaction *trans)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
SplitList *node;
|
|
|
|
gboolean shutting_down = qof_book_shutting_down(qof_instance_get_book(trans));
|
2003-09-03 08:02:37 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* If there are capital-gains transactions associated with this,
|
2011-10-27 22:22:41 -05:00
|
|
|
* they need to be destroyed too unless we're shutting down in
|
|
|
|
* which case all transactions will be destroyed. */
|
|
|
|
if (!shutting_down)
|
2012-01-01 14:36:46 -06:00
|
|
|
destroy_gains (trans);
|
2003-09-03 08:02:37 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Make a log in the journal before destruction. */
|
2011-11-14 15:28:32 -06:00
|
|
|
if (!shutting_down && !qof_book_is_readonly(qof_instance_get_book(trans)))
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransWriteLog (trans, 'D');
|
2003-09-03 08:02:37 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_event_gen (&trans->inst, QOF_EVENT_DESTROY, NULL);
|
2003-09-03 08:02:37 -05:00
|
|
|
|
2011-01-09 12:01:47 -06:00
|
|
|
/* We only own the splits that still think they belong to us. This is done
|
|
|
|
in 2 steps. In the first, the splits are marked as being destroyed, but they
|
|
|
|
are not destroyed yet. In the second, the destruction is committed which will
|
|
|
|
do the actual destruction. If both steps are done for a split before they are
|
|
|
|
done for the next split, then a split will still be on the split list after it
|
|
|
|
has been freed. This can cause other parts of the code (e.g. in xaccSplitDestroy())
|
|
|
|
to reference the split after it has been freed. */
|
2010-03-02 15:40:28 -06:00
|
|
|
for (node = trans->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
Split *s = node->data;
|
2013-08-16 11:43:58 -05:00
|
|
|
if (s && s->parent == trans)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
xaccSplitDestroy(s);
|
2011-01-09 12:01:47 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for (node = trans->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
Split *s = node->data;
|
2013-08-16 11:43:58 -05:00
|
|
|
if (s && s->parent == trans)
|
2011-01-09 12:01:47 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccSplitCommitEdit(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_list_free (trans->splits);
|
|
|
|
trans->splits = NULL;
|
|
|
|
xaccFreeTransaction (trans);
|
2003-09-03 08:02:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
|
|
|
|
2010-09-04 08:24:46 -05:00
|
|
|
/* Temporary hack for data consistency */
|
2003-09-20 17:53:28 -05:00
|
|
|
static int scrub_data = 1;
|
2010-03-02 15:40:28 -06:00
|
|
|
void xaccEnableDataScrubbing(void)
|
|
|
|
{
|
|
|
|
scrub_data = 1;
|
|
|
|
}
|
|
|
|
void xaccDisableDataScrubbing(void)
|
|
|
|
{
|
|
|
|
scrub_data = 0;
|
|
|
|
}
|
2003-09-20 17:53:28 -05:00
|
|
|
|
2006-03-03 18:10:12 -06:00
|
|
|
/* Check for an implicitly deleted transaction */
|
|
|
|
static gboolean was_trans_emptied(Transaction *trans)
|
|
|
|
{
|
|
|
|
FOR_EACH_SPLIT(trans, return FALSE);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void trans_on_error(Transaction *trans, QofBackendError errcode)
|
|
|
|
{
|
|
|
|
/* If the backend puked, then we must roll-back
|
|
|
|
* at this point, and let the user know that we failed.
|
|
|
|
* The GUI should check for error conditions ...
|
|
|
|
*/
|
2010-03-02 15:40:28 -06:00
|
|
|
if (ERR_BACKEND_MODIFIED == errcode)
|
|
|
|
{
|
2006-03-03 18:10:12 -06:00
|
|
|
PWARN("Another user has modified this transaction\n"
|
|
|
|
"\tjust a moment ago. Please look at their changes,\n"
|
|
|
|
"\tand try again, if needed.\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
xaccTransRollbackEdit(trans);
|
2008-10-27 18:42:01 -05:00
|
|
|
gnc_engine_signal_commit_error( errcode );
|
2006-03-03 18:10:12 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void trans_cleanup_commit(Transaction *trans)
|
|
|
|
{
|
|
|
|
GList *slist, *node;
|
|
|
|
|
|
|
|
/* ------------------------------------------------- */
|
|
|
|
/* Make sure all associated splits are in proper order
|
|
|
|
* in their accounts with the correct balances. */
|
|
|
|
|
|
|
|
/* Iterate over existing splits */
|
|
|
|
slist = g_list_copy(trans->splits);
|
2010-03-02 15:40:28 -06:00
|
|
|
for (node = slist; node; node = node->next)
|
|
|
|
{
|
2006-03-03 18:10:12 -06:00
|
|
|
Split *s = node->data;
|
|
|
|
if (!qof_instance_is_dirty(QOF_INSTANCE(s)))
|
|
|
|
continue;
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if ((s->parent != trans) || qof_instance_get_destroying(s))
|
|
|
|
{
|
2006-03-03 18:10:12 -06:00
|
|
|
/* Existing split either moved to another transaction or
|
|
|
|
was destroyed, drop from list */
|
2006-03-03 21:21:34 -06:00
|
|
|
GncEventData ed;
|
2006-03-04 17:06:39 -06:00
|
|
|
ed.node = trans;
|
2006-03-03 21:21:34 -06:00
|
|
|
ed.idx = g_list_index(trans->splits, s);
|
2006-03-03 18:10:12 -06:00
|
|
|
trans->splits = g_list_remove(trans->splits, s);
|
2007-04-01 17:18:50 -05:00
|
|
|
qof_event_gen(&s->inst, QOF_EVENT_REMOVE, &ed);
|
2006-03-03 18:10:12 -06:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (s->parent == trans)
|
|
|
|
{
|
2006-04-10 21:55:57 -05:00
|
|
|
/* Split was either added, destroyed or just changed */
|
2007-04-30 00:33:33 -05:00
|
|
|
if (qof_instance_get_destroying(s))
|
2007-04-01 17:18:50 -05:00
|
|
|
qof_event_gen(&s->inst, QOF_EVENT_DESTROY, NULL);
|
|
|
|
else qof_event_gen(&s->inst, QOF_EVENT_MODIFY, NULL);
|
2006-03-03 18:10:12 -06:00
|
|
|
xaccSplitCommitEdit(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_list_free(slist);
|
|
|
|
|
2011-11-14 15:28:32 -06:00
|
|
|
if (!qof_book_is_readonly(qof_instance_get_book(trans)))
|
|
|
|
xaccTransWriteLog (trans, 'C');
|
2006-03-03 18:10:12 -06:00
|
|
|
|
|
|
|
/* Get rid of the copy we made. We won't be rolling back,
|
|
|
|
* so we don't need it any more. */
|
|
|
|
PINFO ("get rid of rollback trans=%p", trans->orig);
|
|
|
|
xaccFreeTransaction (trans->orig);
|
|
|
|
trans->orig = NULL;
|
|
|
|
|
|
|
|
/* Sort the splits. Why do we need to do this ?? */
|
|
|
|
/* Good question. Who knows? */
|
|
|
|
xaccTransSortSplits(trans);
|
|
|
|
|
|
|
|
/* Put back to zero. */
|
2007-04-30 00:33:33 -05:00
|
|
|
qof_instance_decrease_editlevel(trans);
|
|
|
|
g_assert(qof_instance_get_editlevel(trans) == 0);
|
2006-03-03 18:10:12 -06:00
|
|
|
|
|
|
|
gen_event_trans (trans); //TODO: could be conditional
|
2007-04-01 17:18:50 -05:00
|
|
|
qof_event_gen (&trans->inst, QOF_EVENT_MODIFY, NULL);
|
2006-03-03 18:10:12 -06:00
|
|
|
}
|
2003-09-20 17:53:28 -05:00
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
void
|
|
|
|
xaccTransCommitEdit (Transaction *trans)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans) return;
|
|
|
|
ENTER ("(trans=%p)", trans);
|
|
|
|
|
|
|
|
if (!qof_commit_edit (QOF_INSTANCE(trans)))
|
|
|
|
{
|
|
|
|
LEAVE("editlevel non-zero");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We increment this for the duration of the call
|
|
|
|
* so other functions don't result in a recursive
|
|
|
|
* call to xaccTransCommitEdit. */
|
|
|
|
qof_instance_increase_editlevel(trans);
|
|
|
|
|
|
|
|
if (was_trans_emptied(trans))
|
|
|
|
qof_instance_set_destroying(trans, TRUE);
|
|
|
|
|
2010-09-04 08:24:46 -05:00
|
|
|
/* Before committing the transaction, we are going to enforce certain
|
2010-03-02 15:40:28 -06:00
|
|
|
* constraints. In particular, we want to enforce the cap-gains
|
|
|
|
* and the balanced lot constraints. These constraints might
|
|
|
|
* change the number of splits in this transaction, and the
|
|
|
|
* transaction itself might be deleted. This is also why
|
|
|
|
* we can't really enforce these constraints elsewhere: they
|
2010-09-04 08:24:46 -05:00
|
|
|
* can cause pointers to splits and transactions to disappear out
|
2010-03-02 15:40:28 -06:00
|
|
|
* from under the holder.
|
|
|
|
*/
|
|
|
|
if (!qof_instance_get_destroying(trans) && scrub_data &&
|
|
|
|
!qof_book_shutting_down(xaccTransGetBook(trans)))
|
|
|
|
{
|
|
|
|
/* If scrubbing gains recurses through here, don't call it again. */
|
|
|
|
scrub_data = 0;
|
|
|
|
/* The total value of the transaction should sum to zero.
|
2010-09-04 08:24:46 -05:00
|
|
|
* Call the trans scrub routine to fix it. Indirectly, this
|
2010-03-02 15:40:28 -06:00
|
|
|
* routine also performs a number of other transaction fixes too.
|
|
|
|
*/
|
|
|
|
xaccTransScrubImbalance (trans, NULL, NULL);
|
|
|
|
/* Get the cap gains into a consistent state as well. */
|
|
|
|
|
|
|
|
/* Lot Scrubbing is temporarily disabled. */
|
|
|
|
if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
|
|
|
|
xaccTransScrubGains (trans, NULL);
|
|
|
|
|
|
|
|
/* Allow scrubbing in transaction commit again */
|
|
|
|
scrub_data = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Record the time of last modification */
|
2017-12-31 06:37:02 -06:00
|
|
|
if (0 == trans->date_entered)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2017-12-31 06:37:02 -06:00
|
|
|
trans->date_entered = gnc_time(NULL);
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_instance_set_dirty(QOF_INSTANCE(trans));
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_commit_edit_part2(QOF_INSTANCE(trans),
|
|
|
|
(void (*) (QofInstance *, QofBackendError))
|
|
|
|
trans_on_error,
|
|
|
|
(void (*) (QofInstance *)) trans_cleanup_commit,
|
|
|
|
(void (*) (QofInstance *)) do_destroy);
|
|
|
|
LEAVE ("(trans=%p)", trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2021-07-08 14:42:03 -05:00
|
|
|
#define SWAP_STR(a, b) do { const char *tmp = (a); (a) = (b); (b) = tmp; } while (0);
|
|
|
|
#define SWAP(a, b) do { gpointer tmp = (a); (a) = (b); (b) = tmp; } while (0);
|
2006-03-03 18:10:12 -06:00
|
|
|
|
2003-09-21 21:54:16 -05:00
|
|
|
/* Ughhh. The Rollback function is terribly complex, and, what's worse,
|
|
|
|
* it only rolls back the basics. The TransCommit functions did a bunch
|
|
|
|
* of Lot/Cap-gains scrubbing that don't get addressed/undone here, and
|
|
|
|
* so the rollback can potentially leave a bit of a mess behind. We
|
|
|
|
* really need a more robust undo capability. Part of the problem is
|
|
|
|
* that the biggest user of the undo is the multi-user backend, which
|
|
|
|
* also adds complexity.
|
|
|
|
*/
|
2001-08-07 18:36:04 -05:00
|
|
|
void
|
|
|
|
xaccTransRollbackEdit (Transaction *trans)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *node, *onode;
|
|
|
|
QofBackend *be;
|
|
|
|
Transaction *orig;
|
|
|
|
GList *slist;
|
|
|
|
int num_preexist, i;
|
2013-08-16 11:44:28 -05:00
|
|
|
|
|
|
|
/* FIXME: This isn't quite the right way to handle nested edits --
|
|
|
|
* there should be a stack of transaction states that are popped off
|
|
|
|
* and restored at each level -- but it does prevent restoring to the
|
|
|
|
* editlevel 0 state until one is returning to editlevel 0, and
|
|
|
|
* thereby prevents a crash caused by trans->orig getting NULLed too
|
|
|
|
* soon.
|
|
|
|
*/
|
|
|
|
if (!qof_instance_get_editlevel (QOF_INSTANCE (trans))) return;
|
|
|
|
if (qof_instance_get_editlevel (QOF_INSTANCE (trans)) > 1) {
|
|
|
|
qof_instance_decrease_editlevel (QOF_INSTANCE (trans));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER ("trans addr=%p\n", trans);
|
|
|
|
|
|
|
|
check_open(trans);
|
|
|
|
|
|
|
|
/* copy the original values back in. */
|
2013-08-16 11:44:28 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
orig = trans->orig;
|
2021-07-08 14:42:03 -05:00
|
|
|
SWAP_STR(trans->num, orig->num);
|
|
|
|
SWAP_STR(trans->description, orig->description);
|
2010-03-02 15:40:28 -06:00
|
|
|
trans->date_entered = orig->date_entered;
|
|
|
|
trans->date_posted = orig->date_posted;
|
|
|
|
SWAP(trans->common_currency, orig->common_currency);
|
2015-05-08 15:33:40 -05:00
|
|
|
qof_instance_swap_kvp (QOF_INSTANCE (trans), QOF_INSTANCE (orig));
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
/* The splits at the front of trans->splits are exactly the same
|
|
|
|
splits as in the original, but some of them may have changed, so
|
|
|
|
we restore only those. */
|
2013-08-16 11:43:30 -05:00
|
|
|
/* FIXME: Runs off the transaction's splits, so deleted splits are not
|
|
|
|
* restored!
|
|
|
|
*/
|
2010-03-02 15:40:28 -06:00
|
|
|
num_preexist = g_list_length(orig->splits);
|
|
|
|
slist = g_list_copy(trans->splits);
|
|
|
|
for (i = 0, node = slist, onode = orig->splits; node;
|
|
|
|
i++, node = node->next, onode = onode ? onode->next : NULL)
|
|
|
|
{
|
|
|
|
Split *s = node->data;
|
|
|
|
|
|
|
|
if (!qof_instance_is_dirty(QOF_INSTANCE(s)))
|
|
|
|
continue;
|
|
|
|
|
2018-11-28 00:40:21 -06:00
|
|
|
if (i < num_preexist && onode)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
Split *so = onode->data;
|
|
|
|
|
|
|
|
xaccSplitRollbackEdit(s);
|
2021-07-08 14:42:03 -05:00
|
|
|
SWAP_STR(s->action, so->action);
|
|
|
|
SWAP_STR(s->memo, so->memo);
|
2015-05-08 15:33:40 -05:00
|
|
|
qof_instance_copy_kvp (QOF_INSTANCE (s), QOF_INSTANCE (so));
|
2010-03-02 15:40:28 -06:00
|
|
|
s->reconciled = so->reconciled;
|
|
|
|
s->amount = so->amount;
|
|
|
|
s->value = so->value;
|
|
|
|
s->lot = so->lot;
|
2011-12-08 11:11:21 -06:00
|
|
|
s->gains_split = so->gains_split;
|
2010-03-02 15:40:28 -06:00
|
|
|
//SET_GAINS_A_VDIRTY(s);
|
|
|
|
s->date_reconciled = so->date_reconciled;
|
|
|
|
qof_instance_mark_clean(QOF_INSTANCE(s));
|
|
|
|
xaccFreeSplit(so);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Potentially added splits */
|
|
|
|
if (trans != xaccSplitGetParent(s))
|
|
|
|
{
|
|
|
|
trans->splits = g_list_remove(trans->splits, s);
|
|
|
|
/* New split added, but then moved to another
|
|
|
|
transaction */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
xaccSplitRollbackEdit(s);
|
|
|
|
trans->splits = g_list_remove(trans->splits, s);
|
|
|
|
g_assert(trans != xaccSplitGetParent(s));
|
|
|
|
/* NB: our memory management policy here is that a new split
|
|
|
|
added to the transaction which is then rolled-back still
|
|
|
|
belongs to the engine. Specifically, it's freed by the
|
|
|
|
transaction to which it was added. Don't add the Split to
|
|
|
|
more than one transaction during the begin/commit block! */
|
|
|
|
if (NULL == xaccSplitGetParent(s))
|
|
|
|
{
|
|
|
|
xaccFreeSplit(s); // a newly malloc'd split
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_list_free(slist);
|
|
|
|
g_list_free(orig->splits);
|
|
|
|
orig->splits = NULL;
|
|
|
|
|
|
|
|
/* Now that the engine copy is back to its original version,
|
|
|
|
* get the backend to fix it in the database */
|
|
|
|
be = qof_book_get_backend(qof_instance_get_book(trans));
|
|
|
|
/** \todo Fix transrollbackedit in QOF so that rollback
|
|
|
|
is exposed via the API. */
|
2016-02-16 19:11:55 -06:00
|
|
|
if (qof_backend_can_rollback (be))
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
QofBackendError errcode;
|
|
|
|
|
|
|
|
/* clear errors */
|
|
|
|
do
|
|
|
|
{
|
|
|
|
errcode = qof_backend_get_error (be);
|
|
|
|
}
|
|
|
|
while (ERR_BACKEND_NO_ERR != errcode);
|
|
|
|
|
2016-02-16 19:11:55 -06:00
|
|
|
qof_backend_rollback_instance (be, &(trans->inst));
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2003-06-26 21:51:10 -05:00
|
|
|
errcode = qof_backend_get_error (be);
|
2010-03-02 15:40:28 -06:00
|
|
|
if (ERR_BACKEND_MOD_DESTROY == errcode)
|
|
|
|
{
|
|
|
|
/* The backend is asking us to delete this transaction.
|
|
|
|
* This typically happens because another (remote) user
|
|
|
|
* has deleted this transaction, and we haven't found
|
|
|
|
* out about it until this user tried to edit it.
|
|
|
|
*/
|
|
|
|
xaccTransDestroy (trans);
|
|
|
|
do_destroy (trans);
|
|
|
|
|
|
|
|
/* push error back onto the stack */
|
|
|
|
qof_backend_set_error (be, errcode);
|
|
|
|
LEAVE ("deleted trans addr=%p\n", trans);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (ERR_BACKEND_NO_ERR != errcode)
|
|
|
|
{
|
|
|
|
PERR ("Rollback Failed. Ouch!");
|
|
|
|
/* push error back onto the stack */
|
|
|
|
qof_backend_set_error (be, errcode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-14 15:28:32 -06:00
|
|
|
if (!qof_book_is_readonly(qof_instance_get_book(trans)))
|
|
|
|
xaccTransWriteLog (trans, 'R');
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
xaccFreeTransaction (trans->orig);
|
|
|
|
|
|
|
|
trans->orig = NULL;
|
|
|
|
qof_instance_set_destroying(trans, FALSE);
|
|
|
|
|
|
|
|
/* Put back to zero. */
|
|
|
|
qof_instance_decrease_editlevel(trans);
|
|
|
|
/* FIXME: The register code seems to depend on the engine to
|
|
|
|
generate an event during rollback, even though the state is just
|
|
|
|
reverting to what it was. */
|
|
|
|
gen_event_trans (trans);
|
|
|
|
|
|
|
|
LEAVE ("trans addr=%p\n", trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2002-12-07 07:05:45 -06:00
|
|
|
xaccTransIsOpen (const Transaction *trans)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
return trans ? (0 < qof_instance_get_editlevel(trans)) : FALSE;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2006-03-05 15:14:19 -06:00
|
|
|
#define SECS_PER_DAY 86400
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
int
|
2002-12-07 07:05:45 -06:00
|
|
|
xaccTransOrder (const Transaction *ta, const Transaction *tb)
|
Implement a Book Option to give users the choice to use the transaction number field (default and current behaviour) or, alternatively, the split action field of the anchor split for 'Num' column on registers, reports, import and export, where applicable. The difference between the two is that with the default, the same 'Num' is displayed for a given transaction regardless of what register it is viewed in and with the new option, a different 'Num' can be entered/displayed for a given transaction in each register it is viewed in. In both cases, the 'next number logic' of the 'Num' cell is based on the account of the register the transaction is entered/viewed from but in one case it fills the transaction number, in the other, it fills the split action field of the anchor split (with the transaction number field displayed in the register cell labeled 'T-Num'). In both cases, both fields are visible and can be used as free-form text in double-line mode for any value the user wants. If the new option is not selected, there should be no change in Gnucash's behaviour with the exception of displaying the book options dialog in 'new book' situations.
The changes made are:
1. Implement the new book option to select source for 'num' cell:
libqof/qof/qofbookslots.h - define num source option
engine/engine.i - define 'NUM-FIELD-SOURCE' as an option name and
'SPLIT-ACTION' as a term for sorting queries
app-utils/business-prefs.scm - define book option for num-field-source
app-utils/app-utils.scm - define and export book option for num-field-source
2. Implement functions to get book option setting and to test:
libqof/qof/qofbook.c & .h - define function to get number source book option
libqof/qof/test/test-qofbook.c - test function to get number source book option
3. Implement a notification mechanism for book option changes:
engine/engine-helpers.c & .h - define functions to register callbacks,
define function to remove callbacks and
define function to initiate callbacks on book num-source option changes
core-utils/gnc-features.c & .h - define feature for num-source
app-utils/gnc-ui-util.c & .h - define gnc_book_option_num_field_source_change_cb;
include setting of feature flag on initial use
gnome-utils/gnc-main-window.c - change name of gnc_options_dialog_apply_cb
function to gnc_book_options_dialog_apply_cb and adjust function to
call function gnc_book_option_num_field_source_change_cb when book
option for num-field-source changes; change name of
gnc_options_dialog_close_cb to gnc_book_options_dialog_close_cb
4. Implement 'help' button response on Book Option Dialog:
gnome-utils/gnc-ui.h - define "book-options" section of help manual
gnome-utils/gnc-gnome-utils.c & .h - implement Book Options help callback
gnome-utils/gnc-main-window.c - use gnc_options_dialog_set_book_options_help_cb
to make help button active
5. Implement utility functions to get/set number/action based on book option:
engine/engine-helpers.c & .h - define 'gnc_get_num_action' function
define 'gnc_get_action_num' function
define 'gnc_set_num_action' function
engine/engine.i - make get/set num/action functions available to guile &
allow #f to be used in place of NULL from guile
engine/Transaction.h - add reference to utility functions in comments to
xaccTransSetNum and xaccTransGetNum functions
engine/Split.h - add reference to utility functions in comments to
xaccSplitSetAction and xaccSplitGetAction functions
6. Implement register use of num source book option; for General, Income and Search
Ledgers, since there is no anchor split, always show tran-num in transaction
cursor, but vary label to correspond to book option:
register/ledger-core/split-register.h - define TNUM_CELL
define CURSOR_DOUBLE_LEDGER_NUM_ACTN cursor name to use TNUM_CELL
define CURSOR_DOUBLE_JOURNAL_NUM_ACTN cursor name to use TNUM_CELL
add boolean to split_reg structure to hold num source book option
register/ledger-core/split-register-layout.c -
add logic to define and set up new ledger/journal cursors with TNUM_CELLs
add logic to add the new cursors to a layout
add logic to add TNUM_CELL to a layout
register/ledger-core/split-register-model.c -
define function to get TNUM_CELL label
add logic to recognize ledger/journal cursors with TNUM_CELL
modify function to get NUM_CELL value based on book option and register
type
define function to get TNUM_CELL value
adjust num help text to reflect book option choice
define function to get TNUM_CELL help
modify function to get action help to reflect book option choice
set up handlers for TNUM_CELL
register/ledger-core/split-register-model-save.c -
use 'gnc_set_num_action' function to set num/action for NUM_CELL based
on book option
define function to save TNUM_CELL using 'gnc_set_num_action' function
set save handler for TNUM_CELL
register/ledger-core/split-register-util.c -
modify logic to recognize ledger/journal cursors with tnum_cell
register/ledger-core/split-register.c -
define split_register_book_option_changed function
register split_register_book_option_changed function in register init
initialize register structure setting to book option
remove split_register_book_option_changed function in register destroy
modify gnc_split_register_save_to_scm to handle TNUM_CELL
7. Enhance transaction copy/duplicate logic to accommodate new book option:
gnome/gtkbuilder/gnc-plugin-page-register.glade -
add widgets to handle trans number and/or split action based on book option
gnome-utils/dialog-dup-trans.c & .h -
add capability to display and handle 'Num' field according to book option
gnome/gnc-plugin-page-register.c - define gnc_find_register_by_account
register/ledger-core/split-register.c -
modify gnc_split_register_duplicate_current to accomodate book option
setting
register/ledger-core/Makefile.am - add GNOME_CFLAGS
register/ledger-core/test/Makefile.am - add libgnc-gnome.la
8. Adjust register sort and sort labels related to Num/Action radio buttons to
correspond to book option for clarity:
gnome/gnc-plugin-page-register.c -
define gnc_plugin_page_register_sort_book_option_changed to adjust labels
register function in gnc_plugin_page_register_cmd_view_sort_by
and save num and action radio widgets
initialize radio widget labels to correspond to book option
remove function in gnc_plugin_page_register_sort_response_cb
and clear num and action radio widgets
gnome/gnc-split-reg.c & h. -
create versions of gnc_split_reg_sort and gnc_split_reg_set_sort to force
a re-sort to be used when num-source book option changes
engine/Transaction.c & .h -
modify default sort to use split action in place of tran num per book
option if called from xaccSplitOrder
engine/Split.c -
modify xaccSplitOrder to call xaccTransOrder_num_action to switch use of
split action and tran num per book option
engine/test/utest-Split.c -
modify test_xaccSplitOrder to call xaccTransOrder_num_action based on
book option
9. Adjust transaction find labels related to Num/Action to correspond to book option
for clarity:
gnome/dialog-find-transactions.c - adjust labels in search criteria based
on book option
gnome-search/dialog-search.c -
define gnc_search_dialog_book_option_changed to adjust labels
register function in gnc_search_dialog_init_widgets when searching
for splits
remove function in gnc_search_dialog_close_cb if registered
10. Modify new file process to allow setting of num-source (actually, all) book
option(s) during New Account Hierarchy Setup:
gnome-utils/gtkbuilder/dialog-preferences.glade - add a user preference for
the default setting for 'num-source' for new books
core-utils/gnc-gconf-utils.h - define KEY_NUM_SOURCE
gnome-utils/gnc-gnome-utils.c & h. -
define gnc_options_dialog_set_new_book_option_values to retrieve
preference values
gnome-utils/dialog-options.c & .h - define gnc_options_dialog_new_modal to
surpress apply button
gnome-utils/gnc-main-window.c - define function gnc_book_options_dialog_cb
with arguments so that the window can be called in modal mode and the
title changed and return dialog widget; call gnc_options_dialog_new_modal
instead of gnc_options_dialog_new; call this function from
gnc_main_window_cmd_file_properties with new arguments; for modal mode,
call gnc-options-dialog-set-new-book-option-values to initialize values
from preferences
app-utils/gnc-ui-util.c & h. - create function gnc_is_new_book for
determining when a new book is being created
gnome-utils/dialog-utils.c & h. - define gnc_new_book_option_display to
display book options dialog in modal mode
gnome/gtkbuilder/assistant-hierarchy.glade - add notification about book
options to currency page
gnome/assistant-hierarchy.c - add ability to set book option initialized
from preferences value for new books by using functions gnc_is_new_book
and gnc_new_book_option_display
11. Modify Import QIF process to recognize a new-book situation and allow setting
of book options during first import into a new book; also follow book option
setting for num source in importing number whether new book or not:
import-export/qif-import/assistant-qif-import.glade - add notification about
book options to currency page
import-export/qif-import/assistant-qif-import.c - using function
gnc_is_new_book to identify 'new book' situation and set flag; add
logic to handle 'new-book' situation by calling
gnc_new_book_option_display function
import-export/qif-import/qif-to-gnc.scm - use 'gnc_set_num_action' function
to import number to correct field based on book option
12. Modify Import OFX/QFX process to recognize a new-book situation and allow setting
of book options during first import into a new book; also follow book option
setting for num source in importing number whether new book or not:
import-export/ofx/gnc-ofx-import.c - use 'gnc_set_num_action' function to import
number based on book option; identify 'new book' situation using function
gnc_is_new_book and set flag; add logic to handle 'new-book' situation
by raising book options dialog by calling gnc_new_book_option_display
function
import-export/import-backend.c - use 'gnc_get_num_action' function to
retrieve number from transactions to be matched based on book option
13. Modify Import AqBanking process to recognize a new-book situation and allow
setting of book options during first import into a new book; also follow
book option setting for num source in importing number:
import-export/aqbanking/gnc-file-aqb-import.c - identify 'new book'
situation using function gnc_is_new_book and handle by raising book
options dialog by calling gnc_new_book_option_display function
import-export/aqbanking/gnc-ab-utils.c - use 'gnc_set_num_action' function
to set number based on book option
14. Modify Import Transactions from CSV process to recognize a new-book situation
and allow setting of book options during first import into a new book; also
follow book option setting for num source in importing number whether new
book or not:
import-export/csv-import/assistant-csv-trans-import.glade - modify
commments to alert user of raising book options dialog in cases of csv
import into a new book
import-export/csv-import/gnc-csv-model.c & h. - use 'gnc_set_num_action'
function to import number based on book option
import-export/csv-import/assistant-csv-trans-import.c - add logic to handle
'new-book' situation by raising book options dialog by calling
gnc_new_book_option_display function; identify 'new book' situation
using function gnc_is_new_book and set flag
15. Modify Import Accounts from CSV process to recognize a new-book situation
and allow setting of book options during first import into a new book
import-export/csv-import/assistant-csv-account-import.c & .h - add logic to
handle 'new-book' situation by raising book options dialog by calling
gnc_new_book_option_display function; identify 'new book' situation
using function gnc_is_new_book and set flag
16. Modify Export Transactions to CSV process to follow book option setting
for num source in exporting transactions:
import-export/csv-export/csv-transactions-export.c - modify headings to
reflect num-source book option and use 'gnc_get_num_action' function
to retrieve number and action
17. Modify register reporting to reflect book option setting for num source:
gnome/gnc-plugin-page-register.c - determine and pass along ledger-type?
argument to gnc:register-report-create function
gnome/gnc-plugin-page-register2.c - determine and pass along ledger-type?
argument to gnc:register-report-create function
report/standard-reports/standard-reports.scm - add ledger-type? argument
to gnc:register-report-create function; pass it along to
gnc:register-report-create-internal function
report/standard-reports/register.scm - add ledger-type? argument to
gnc:register-report-create-internal function; use 'gnc-get-num-action'
function in place of xaccTransGetNum and 'gnc-get-action-num' function
in place of xaccSplitGetAction and modify report headings and option
text accordingly
18. Modify all places that use xaccTransSetNum and/or xaccSplitSetAction to use
'gnc_set_num_action' function to set number based on book option except
engine/Transaction.c & .h, engine/test-core/test-engine-stuff.c,
engine/Split.c & .h, engine/test/utest-Split.c, engine/engine-helpers.c & .h,
engine/engine-interface.scm, backend/xml/gnc-transaction-xml-v2.c,
backend/xml/io-gncxml-v1.c, import-export/log-replay/gnc-log-replay.c:
engine/gncOwner.c - use 'gnc_set_num_action' function to set number based
on book option
engine/gncInvoice.c - use 'gnc_set_num_action' function to set number based
on book option
engine/SchedXaction.c - use 'gnc_set_num_action' function to set number and
action
engine/cap-gains.c - use 'gnc_set_num_action' function to set split-action
gnome-utils/dialog-transfer.c - use 'gnc_set_num_action' function to set
number based on book option
gnome-utils/gnc-tree-view-split-reg.c - use 'gnc_set_num_action' function
to set number/action based on book option
gnome/assistant-stock-split.c - use 'gnc_set_num_action' function to set
split-action
19. Modify all places that use xaccTransGetNum and/or xaccSplitGetAction to use
'gnc_get_num_action' or 'gnc_get_action_num' functions to get number based
on book option except engine/Transaction.c & .h,
engine/test-core/test-engine-stuff.c, engine/Split.c & h.,
engine/test/utest-Split.c, engine/engine-helpers.c,
engine/engine-interface.scm, backend/xml/gnc-transaction-xml-v2.c,
backend/xml/test/test-xml-transaction.c:
gnome/dialog-lot-viewer.c - use 'gnc_get_num_action' function to retrieve
number based on book option
gnome/dialog-sx-from-trans.c - use 'gnc_get_num_action' function to
retrieve number and action
gnome/dialog-print-check.c - use 'gnc_get_num_action' function to
retrieve number and 'gnc_get_action_num' function to retrieve action
register/ledger-core/split-register-model.c - use 'gnc_get_num_action'
function to retrieve number based on book option
register/ledger-core/split-register-load.c - use 'gnc_get_num_action'
function to retrieve number based on book option
register/ledger-core/split-register-control.c - use 'gnc_get_num_action'
function to retrieve action
register/ledger-core/split-register.c - use 'gnc_get_num_action'
function to retrieve transaction-num
engine/cap-gains.c - use 'gnc_get_num_action' function to get split-action
gnome-utils/gnc-tree-view-split-reg.c - use 'gnc_get_num_action' function
to retrieve number and 'gnc_get_action_num' function to retrieve action
gnome-utils/gnc-tree-model-split-reg.c - use 'gnc_get_num_action' function
to retrieve transaction-number but may not be getting what is expected
if book option to use split-action for 'num' is set
report/locale-specific/us/taxtxf.scm - use 'gnc-get-num-action' function in
place of xaccTransGetNum and 'gnc-get-action-num' function in place of
xaccSplitGetAction and modify report headings and option text accordingly
report/standard-reports/transaction.scm - use 'gnc-get-num-action' function
in place of xaccTransGetNum, adjust sorting based on book option and
modify report headings and option text accordingly; add 'SPLIT-ACTION'
as a term for sorting queries
report/business-reports/customer-summary.scm - use 'gnc-get-num-action'
function in place of xaccTransGetNum
report/business-reports/owner-report.scm - use 'gnc-get-num-action'
function in place of xaccTransGetNum
report/business-reports/job-report.scm - use 'gnc-get-num-action' function
in place of xaccTransGetNum
business/business-gnome/dialog-payment.c - use 'gnc_get_num_action'
function to retrieve number based on book option
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@22681 57a11ea4-9604-0410-9ed3-97b8803252fd
2012-12-22 00:00:54 -06:00
|
|
|
{
|
|
|
|
return xaccTransOrder_num_action (ta, NULL, tb, NULL);
|
|
|
|
}
|
|
|
|
|
2021-06-08 11:49:46 -05:00
|
|
|
/* Order a pair of potentially numeric string as numbers if both
|
|
|
|
* strings begin with numbers, ordering the remainder of the string
|
|
|
|
* lexically if the numeric parts are equal, and the whole strings
|
|
|
|
* lexically otherwise.
|
|
|
|
*
|
|
|
|
* Note that this won't work well for numbers > 10^18 and that
|
|
|
|
* negative numbers are treated as strings and will cause the pair to
|
|
|
|
* be ordered lexically.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int
|
|
|
|
order_by_int64_or_string (const char* a, const char* b)
|
|
|
|
{
|
|
|
|
char *end_a = NULL, *end_b = NULL;
|
|
|
|
int cmp = 0;
|
|
|
|
uint64_t na = strtoull(a, &end_a, 10);
|
|
|
|
uint64_t nb = strtoull(b, &end_b, 10);
|
|
|
|
if (na && nb)
|
|
|
|
{
|
|
|
|
if (na != nb)
|
|
|
|
return na < nb ? -1 : 1;
|
|
|
|
cmp = g_utf8_collate(end_a, end_b);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cmp = g_utf8_collate(a, b);
|
|
|
|
}
|
|
|
|
return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
Implement a Book Option to give users the choice to use the transaction number field (default and current behaviour) or, alternatively, the split action field of the anchor split for 'Num' column on registers, reports, import and export, where applicable. The difference between the two is that with the default, the same 'Num' is displayed for a given transaction regardless of what register it is viewed in and with the new option, a different 'Num' can be entered/displayed for a given transaction in each register it is viewed in. In both cases, the 'next number logic' of the 'Num' cell is based on the account of the register the transaction is entered/viewed from but in one case it fills the transaction number, in the other, it fills the split action field of the anchor split (with the transaction number field displayed in the register cell labeled 'T-Num'). In both cases, both fields are visible and can be used as free-form text in double-line mode for any value the user wants. If the new option is not selected, there should be no change in Gnucash's behaviour with the exception of displaying the book options dialog in 'new book' situations.
The changes made are:
1. Implement the new book option to select source for 'num' cell:
libqof/qof/qofbookslots.h - define num source option
engine/engine.i - define 'NUM-FIELD-SOURCE' as an option name and
'SPLIT-ACTION' as a term for sorting queries
app-utils/business-prefs.scm - define book option for num-field-source
app-utils/app-utils.scm - define and export book option for num-field-source
2. Implement functions to get book option setting and to test:
libqof/qof/qofbook.c & .h - define function to get number source book option
libqof/qof/test/test-qofbook.c - test function to get number source book option
3. Implement a notification mechanism for book option changes:
engine/engine-helpers.c & .h - define functions to register callbacks,
define function to remove callbacks and
define function to initiate callbacks on book num-source option changes
core-utils/gnc-features.c & .h - define feature for num-source
app-utils/gnc-ui-util.c & .h - define gnc_book_option_num_field_source_change_cb;
include setting of feature flag on initial use
gnome-utils/gnc-main-window.c - change name of gnc_options_dialog_apply_cb
function to gnc_book_options_dialog_apply_cb and adjust function to
call function gnc_book_option_num_field_source_change_cb when book
option for num-field-source changes; change name of
gnc_options_dialog_close_cb to gnc_book_options_dialog_close_cb
4. Implement 'help' button response on Book Option Dialog:
gnome-utils/gnc-ui.h - define "book-options" section of help manual
gnome-utils/gnc-gnome-utils.c & .h - implement Book Options help callback
gnome-utils/gnc-main-window.c - use gnc_options_dialog_set_book_options_help_cb
to make help button active
5. Implement utility functions to get/set number/action based on book option:
engine/engine-helpers.c & .h - define 'gnc_get_num_action' function
define 'gnc_get_action_num' function
define 'gnc_set_num_action' function
engine/engine.i - make get/set num/action functions available to guile &
allow #f to be used in place of NULL from guile
engine/Transaction.h - add reference to utility functions in comments to
xaccTransSetNum and xaccTransGetNum functions
engine/Split.h - add reference to utility functions in comments to
xaccSplitSetAction and xaccSplitGetAction functions
6. Implement register use of num source book option; for General, Income and Search
Ledgers, since there is no anchor split, always show tran-num in transaction
cursor, but vary label to correspond to book option:
register/ledger-core/split-register.h - define TNUM_CELL
define CURSOR_DOUBLE_LEDGER_NUM_ACTN cursor name to use TNUM_CELL
define CURSOR_DOUBLE_JOURNAL_NUM_ACTN cursor name to use TNUM_CELL
add boolean to split_reg structure to hold num source book option
register/ledger-core/split-register-layout.c -
add logic to define and set up new ledger/journal cursors with TNUM_CELLs
add logic to add the new cursors to a layout
add logic to add TNUM_CELL to a layout
register/ledger-core/split-register-model.c -
define function to get TNUM_CELL label
add logic to recognize ledger/journal cursors with TNUM_CELL
modify function to get NUM_CELL value based on book option and register
type
define function to get TNUM_CELL value
adjust num help text to reflect book option choice
define function to get TNUM_CELL help
modify function to get action help to reflect book option choice
set up handlers for TNUM_CELL
register/ledger-core/split-register-model-save.c -
use 'gnc_set_num_action' function to set num/action for NUM_CELL based
on book option
define function to save TNUM_CELL using 'gnc_set_num_action' function
set save handler for TNUM_CELL
register/ledger-core/split-register-util.c -
modify logic to recognize ledger/journal cursors with tnum_cell
register/ledger-core/split-register.c -
define split_register_book_option_changed function
register split_register_book_option_changed function in register init
initialize register structure setting to book option
remove split_register_book_option_changed function in register destroy
modify gnc_split_register_save_to_scm to handle TNUM_CELL
7. Enhance transaction copy/duplicate logic to accommodate new book option:
gnome/gtkbuilder/gnc-plugin-page-register.glade -
add widgets to handle trans number and/or split action based on book option
gnome-utils/dialog-dup-trans.c & .h -
add capability to display and handle 'Num' field according to book option
gnome/gnc-plugin-page-register.c - define gnc_find_register_by_account
register/ledger-core/split-register.c -
modify gnc_split_register_duplicate_current to accomodate book option
setting
register/ledger-core/Makefile.am - add GNOME_CFLAGS
register/ledger-core/test/Makefile.am - add libgnc-gnome.la
8. Adjust register sort and sort labels related to Num/Action radio buttons to
correspond to book option for clarity:
gnome/gnc-plugin-page-register.c -
define gnc_plugin_page_register_sort_book_option_changed to adjust labels
register function in gnc_plugin_page_register_cmd_view_sort_by
and save num and action radio widgets
initialize radio widget labels to correspond to book option
remove function in gnc_plugin_page_register_sort_response_cb
and clear num and action radio widgets
gnome/gnc-split-reg.c & h. -
create versions of gnc_split_reg_sort and gnc_split_reg_set_sort to force
a re-sort to be used when num-source book option changes
engine/Transaction.c & .h -
modify default sort to use split action in place of tran num per book
option if called from xaccSplitOrder
engine/Split.c -
modify xaccSplitOrder to call xaccTransOrder_num_action to switch use of
split action and tran num per book option
engine/test/utest-Split.c -
modify test_xaccSplitOrder to call xaccTransOrder_num_action based on
book option
9. Adjust transaction find labels related to Num/Action to correspond to book option
for clarity:
gnome/dialog-find-transactions.c - adjust labels in search criteria based
on book option
gnome-search/dialog-search.c -
define gnc_search_dialog_book_option_changed to adjust labels
register function in gnc_search_dialog_init_widgets when searching
for splits
remove function in gnc_search_dialog_close_cb if registered
10. Modify new file process to allow setting of num-source (actually, all) book
option(s) during New Account Hierarchy Setup:
gnome-utils/gtkbuilder/dialog-preferences.glade - add a user preference for
the default setting for 'num-source' for new books
core-utils/gnc-gconf-utils.h - define KEY_NUM_SOURCE
gnome-utils/gnc-gnome-utils.c & h. -
define gnc_options_dialog_set_new_book_option_values to retrieve
preference values
gnome-utils/dialog-options.c & .h - define gnc_options_dialog_new_modal to
surpress apply button
gnome-utils/gnc-main-window.c - define function gnc_book_options_dialog_cb
with arguments so that the window can be called in modal mode and the
title changed and return dialog widget; call gnc_options_dialog_new_modal
instead of gnc_options_dialog_new; call this function from
gnc_main_window_cmd_file_properties with new arguments; for modal mode,
call gnc-options-dialog-set-new-book-option-values to initialize values
from preferences
app-utils/gnc-ui-util.c & h. - create function gnc_is_new_book for
determining when a new book is being created
gnome-utils/dialog-utils.c & h. - define gnc_new_book_option_display to
display book options dialog in modal mode
gnome/gtkbuilder/assistant-hierarchy.glade - add notification about book
options to currency page
gnome/assistant-hierarchy.c - add ability to set book option initialized
from preferences value for new books by using functions gnc_is_new_book
and gnc_new_book_option_display
11. Modify Import QIF process to recognize a new-book situation and allow setting
of book options during first import into a new book; also follow book option
setting for num source in importing number whether new book or not:
import-export/qif-import/assistant-qif-import.glade - add notification about
book options to currency page
import-export/qif-import/assistant-qif-import.c - using function
gnc_is_new_book to identify 'new book' situation and set flag; add
logic to handle 'new-book' situation by calling
gnc_new_book_option_display function
import-export/qif-import/qif-to-gnc.scm - use 'gnc_set_num_action' function
to import number to correct field based on book option
12. Modify Import OFX/QFX process to recognize a new-book situation and allow setting
of book options during first import into a new book; also follow book option
setting for num source in importing number whether new book or not:
import-export/ofx/gnc-ofx-import.c - use 'gnc_set_num_action' function to import
number based on book option; identify 'new book' situation using function
gnc_is_new_book and set flag; add logic to handle 'new-book' situation
by raising book options dialog by calling gnc_new_book_option_display
function
import-export/import-backend.c - use 'gnc_get_num_action' function to
retrieve number from transactions to be matched based on book option
13. Modify Import AqBanking process to recognize a new-book situation and allow
setting of book options during first import into a new book; also follow
book option setting for num source in importing number:
import-export/aqbanking/gnc-file-aqb-import.c - identify 'new book'
situation using function gnc_is_new_book and handle by raising book
options dialog by calling gnc_new_book_option_display function
import-export/aqbanking/gnc-ab-utils.c - use 'gnc_set_num_action' function
to set number based on book option
14. Modify Import Transactions from CSV process to recognize a new-book situation
and allow setting of book options during first import into a new book; also
follow book option setting for num source in importing number whether new
book or not:
import-export/csv-import/assistant-csv-trans-import.glade - modify
commments to alert user of raising book options dialog in cases of csv
import into a new book
import-export/csv-import/gnc-csv-model.c & h. - use 'gnc_set_num_action'
function to import number based on book option
import-export/csv-import/assistant-csv-trans-import.c - add logic to handle
'new-book' situation by raising book options dialog by calling
gnc_new_book_option_display function; identify 'new book' situation
using function gnc_is_new_book and set flag
15. Modify Import Accounts from CSV process to recognize a new-book situation
and allow setting of book options during first import into a new book
import-export/csv-import/assistant-csv-account-import.c & .h - add logic to
handle 'new-book' situation by raising book options dialog by calling
gnc_new_book_option_display function; identify 'new book' situation
using function gnc_is_new_book and set flag
16. Modify Export Transactions to CSV process to follow book option setting
for num source in exporting transactions:
import-export/csv-export/csv-transactions-export.c - modify headings to
reflect num-source book option and use 'gnc_get_num_action' function
to retrieve number and action
17. Modify register reporting to reflect book option setting for num source:
gnome/gnc-plugin-page-register.c - determine and pass along ledger-type?
argument to gnc:register-report-create function
gnome/gnc-plugin-page-register2.c - determine and pass along ledger-type?
argument to gnc:register-report-create function
report/standard-reports/standard-reports.scm - add ledger-type? argument
to gnc:register-report-create function; pass it along to
gnc:register-report-create-internal function
report/standard-reports/register.scm - add ledger-type? argument to
gnc:register-report-create-internal function; use 'gnc-get-num-action'
function in place of xaccTransGetNum and 'gnc-get-action-num' function
in place of xaccSplitGetAction and modify report headings and option
text accordingly
18. Modify all places that use xaccTransSetNum and/or xaccSplitSetAction to use
'gnc_set_num_action' function to set number based on book option except
engine/Transaction.c & .h, engine/test-core/test-engine-stuff.c,
engine/Split.c & .h, engine/test/utest-Split.c, engine/engine-helpers.c & .h,
engine/engine-interface.scm, backend/xml/gnc-transaction-xml-v2.c,
backend/xml/io-gncxml-v1.c, import-export/log-replay/gnc-log-replay.c:
engine/gncOwner.c - use 'gnc_set_num_action' function to set number based
on book option
engine/gncInvoice.c - use 'gnc_set_num_action' function to set number based
on book option
engine/SchedXaction.c - use 'gnc_set_num_action' function to set number and
action
engine/cap-gains.c - use 'gnc_set_num_action' function to set split-action
gnome-utils/dialog-transfer.c - use 'gnc_set_num_action' function to set
number based on book option
gnome-utils/gnc-tree-view-split-reg.c - use 'gnc_set_num_action' function
to set number/action based on book option
gnome/assistant-stock-split.c - use 'gnc_set_num_action' function to set
split-action
19. Modify all places that use xaccTransGetNum and/or xaccSplitGetAction to use
'gnc_get_num_action' or 'gnc_get_action_num' functions to get number based
on book option except engine/Transaction.c & .h,
engine/test-core/test-engine-stuff.c, engine/Split.c & h.,
engine/test/utest-Split.c, engine/engine-helpers.c,
engine/engine-interface.scm, backend/xml/gnc-transaction-xml-v2.c,
backend/xml/test/test-xml-transaction.c:
gnome/dialog-lot-viewer.c - use 'gnc_get_num_action' function to retrieve
number based on book option
gnome/dialog-sx-from-trans.c - use 'gnc_get_num_action' function to
retrieve number and action
gnome/dialog-print-check.c - use 'gnc_get_num_action' function to
retrieve number and 'gnc_get_action_num' function to retrieve action
register/ledger-core/split-register-model.c - use 'gnc_get_num_action'
function to retrieve number based on book option
register/ledger-core/split-register-load.c - use 'gnc_get_num_action'
function to retrieve number based on book option
register/ledger-core/split-register-control.c - use 'gnc_get_num_action'
function to retrieve action
register/ledger-core/split-register.c - use 'gnc_get_num_action'
function to retrieve transaction-num
engine/cap-gains.c - use 'gnc_get_num_action' function to get split-action
gnome-utils/gnc-tree-view-split-reg.c - use 'gnc_get_num_action' function
to retrieve number and 'gnc_get_action_num' function to retrieve action
gnome-utils/gnc-tree-model-split-reg.c - use 'gnc_get_num_action' function
to retrieve transaction-number but may not be getting what is expected
if book option to use split-action for 'num' is set
report/locale-specific/us/taxtxf.scm - use 'gnc-get-num-action' function in
place of xaccTransGetNum and 'gnc-get-action-num' function in place of
xaccSplitGetAction and modify report headings and option text accordingly
report/standard-reports/transaction.scm - use 'gnc-get-num-action' function
in place of xaccTransGetNum, adjust sorting based on book option and
modify report headings and option text accordingly; add 'SPLIT-ACTION'
as a term for sorting queries
report/business-reports/customer-summary.scm - use 'gnc-get-num-action'
function in place of xaccTransGetNum
report/business-reports/owner-report.scm - use 'gnc-get-num-action'
function in place of xaccTransGetNum
report/business-reports/job-report.scm - use 'gnc-get-num-action' function
in place of xaccTransGetNum
business/business-gnome/dialog-payment.c - use 'gnc_get_num_action'
function to retrieve number based on book option
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@22681 57a11ea4-9604-0410-9ed3-97b8803252fd
2012-12-22 00:00:54 -06:00
|
|
|
int
|
|
|
|
xaccTransOrder_num_action (const Transaction *ta, const char *actna,
|
|
|
|
const Transaction *tb, const char *actnb)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2021-07-08 14:42:03 -05:00
|
|
|
const char *da, *db;
|
2021-06-08 11:49:46 -05:00
|
|
|
int retval;
|
|
|
|
int64_t na, nb;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if ( ta && !tb ) return -1;
|
|
|
|
if ( !ta && tb ) return +1;
|
|
|
|
if ( !ta && !tb ) return 0;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2017-12-31 06:37:02 -06:00
|
|
|
if (ta->date_posted != tb->date_posted)
|
|
|
|
return (ta->date_posted > tb->date_posted) - (ta->date_posted < tb->date_posted);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2018-11-20 11:55:09 -06:00
|
|
|
/* Always sort closing transactions after normal transactions */
|
|
|
|
{
|
|
|
|
gboolean ta_is_closing = xaccTransGetIsClosingTxn (ta);
|
|
|
|
gboolean tb_is_closing = xaccTransGetIsClosingTxn (tb);
|
|
|
|
if (ta_is_closing != tb_is_closing)
|
|
|
|
return (ta_is_closing - tb_is_closing);
|
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* otherwise, sort on number string */
|
Implement a Book Option to give users the choice to use the transaction number field (default and current behaviour) or, alternatively, the split action field of the anchor split for 'Num' column on registers, reports, import and export, where applicable. The difference between the two is that with the default, the same 'Num' is displayed for a given transaction regardless of what register it is viewed in and with the new option, a different 'Num' can be entered/displayed for a given transaction in each register it is viewed in. In both cases, the 'next number logic' of the 'Num' cell is based on the account of the register the transaction is entered/viewed from but in one case it fills the transaction number, in the other, it fills the split action field of the anchor split (with the transaction number field displayed in the register cell labeled 'T-Num'). In both cases, both fields are visible and can be used as free-form text in double-line mode for any value the user wants. If the new option is not selected, there should be no change in Gnucash's behaviour with the exception of displaying the book options dialog in 'new book' situations.
The changes made are:
1. Implement the new book option to select source for 'num' cell:
libqof/qof/qofbookslots.h - define num source option
engine/engine.i - define 'NUM-FIELD-SOURCE' as an option name and
'SPLIT-ACTION' as a term for sorting queries
app-utils/business-prefs.scm - define book option for num-field-source
app-utils/app-utils.scm - define and export book option for num-field-source
2. Implement functions to get book option setting and to test:
libqof/qof/qofbook.c & .h - define function to get number source book option
libqof/qof/test/test-qofbook.c - test function to get number source book option
3. Implement a notification mechanism for book option changes:
engine/engine-helpers.c & .h - define functions to register callbacks,
define function to remove callbacks and
define function to initiate callbacks on book num-source option changes
core-utils/gnc-features.c & .h - define feature for num-source
app-utils/gnc-ui-util.c & .h - define gnc_book_option_num_field_source_change_cb;
include setting of feature flag on initial use
gnome-utils/gnc-main-window.c - change name of gnc_options_dialog_apply_cb
function to gnc_book_options_dialog_apply_cb and adjust function to
call function gnc_book_option_num_field_source_change_cb when book
option for num-field-source changes; change name of
gnc_options_dialog_close_cb to gnc_book_options_dialog_close_cb
4. Implement 'help' button response on Book Option Dialog:
gnome-utils/gnc-ui.h - define "book-options" section of help manual
gnome-utils/gnc-gnome-utils.c & .h - implement Book Options help callback
gnome-utils/gnc-main-window.c - use gnc_options_dialog_set_book_options_help_cb
to make help button active
5. Implement utility functions to get/set number/action based on book option:
engine/engine-helpers.c & .h - define 'gnc_get_num_action' function
define 'gnc_get_action_num' function
define 'gnc_set_num_action' function
engine/engine.i - make get/set num/action functions available to guile &
allow #f to be used in place of NULL from guile
engine/Transaction.h - add reference to utility functions in comments to
xaccTransSetNum and xaccTransGetNum functions
engine/Split.h - add reference to utility functions in comments to
xaccSplitSetAction and xaccSplitGetAction functions
6. Implement register use of num source book option; for General, Income and Search
Ledgers, since there is no anchor split, always show tran-num in transaction
cursor, but vary label to correspond to book option:
register/ledger-core/split-register.h - define TNUM_CELL
define CURSOR_DOUBLE_LEDGER_NUM_ACTN cursor name to use TNUM_CELL
define CURSOR_DOUBLE_JOURNAL_NUM_ACTN cursor name to use TNUM_CELL
add boolean to split_reg structure to hold num source book option
register/ledger-core/split-register-layout.c -
add logic to define and set up new ledger/journal cursors with TNUM_CELLs
add logic to add the new cursors to a layout
add logic to add TNUM_CELL to a layout
register/ledger-core/split-register-model.c -
define function to get TNUM_CELL label
add logic to recognize ledger/journal cursors with TNUM_CELL
modify function to get NUM_CELL value based on book option and register
type
define function to get TNUM_CELL value
adjust num help text to reflect book option choice
define function to get TNUM_CELL help
modify function to get action help to reflect book option choice
set up handlers for TNUM_CELL
register/ledger-core/split-register-model-save.c -
use 'gnc_set_num_action' function to set num/action for NUM_CELL based
on book option
define function to save TNUM_CELL using 'gnc_set_num_action' function
set save handler for TNUM_CELL
register/ledger-core/split-register-util.c -
modify logic to recognize ledger/journal cursors with tnum_cell
register/ledger-core/split-register.c -
define split_register_book_option_changed function
register split_register_book_option_changed function in register init
initialize register structure setting to book option
remove split_register_book_option_changed function in register destroy
modify gnc_split_register_save_to_scm to handle TNUM_CELL
7. Enhance transaction copy/duplicate logic to accommodate new book option:
gnome/gtkbuilder/gnc-plugin-page-register.glade -
add widgets to handle trans number and/or split action based on book option
gnome-utils/dialog-dup-trans.c & .h -
add capability to display and handle 'Num' field according to book option
gnome/gnc-plugin-page-register.c - define gnc_find_register_by_account
register/ledger-core/split-register.c -
modify gnc_split_register_duplicate_current to accomodate book option
setting
register/ledger-core/Makefile.am - add GNOME_CFLAGS
register/ledger-core/test/Makefile.am - add libgnc-gnome.la
8. Adjust register sort and sort labels related to Num/Action radio buttons to
correspond to book option for clarity:
gnome/gnc-plugin-page-register.c -
define gnc_plugin_page_register_sort_book_option_changed to adjust labels
register function in gnc_plugin_page_register_cmd_view_sort_by
and save num and action radio widgets
initialize radio widget labels to correspond to book option
remove function in gnc_plugin_page_register_sort_response_cb
and clear num and action radio widgets
gnome/gnc-split-reg.c & h. -
create versions of gnc_split_reg_sort and gnc_split_reg_set_sort to force
a re-sort to be used when num-source book option changes
engine/Transaction.c & .h -
modify default sort to use split action in place of tran num per book
option if called from xaccSplitOrder
engine/Split.c -
modify xaccSplitOrder to call xaccTransOrder_num_action to switch use of
split action and tran num per book option
engine/test/utest-Split.c -
modify test_xaccSplitOrder to call xaccTransOrder_num_action based on
book option
9. Adjust transaction find labels related to Num/Action to correspond to book option
for clarity:
gnome/dialog-find-transactions.c - adjust labels in search criteria based
on book option
gnome-search/dialog-search.c -
define gnc_search_dialog_book_option_changed to adjust labels
register function in gnc_search_dialog_init_widgets when searching
for splits
remove function in gnc_search_dialog_close_cb if registered
10. Modify new file process to allow setting of num-source (actually, all) book
option(s) during New Account Hierarchy Setup:
gnome-utils/gtkbuilder/dialog-preferences.glade - add a user preference for
the default setting for 'num-source' for new books
core-utils/gnc-gconf-utils.h - define KEY_NUM_SOURCE
gnome-utils/gnc-gnome-utils.c & h. -
define gnc_options_dialog_set_new_book_option_values to retrieve
preference values
gnome-utils/dialog-options.c & .h - define gnc_options_dialog_new_modal to
surpress apply button
gnome-utils/gnc-main-window.c - define function gnc_book_options_dialog_cb
with arguments so that the window can be called in modal mode and the
title changed and return dialog widget; call gnc_options_dialog_new_modal
instead of gnc_options_dialog_new; call this function from
gnc_main_window_cmd_file_properties with new arguments; for modal mode,
call gnc-options-dialog-set-new-book-option-values to initialize values
from preferences
app-utils/gnc-ui-util.c & h. - create function gnc_is_new_book for
determining when a new book is being created
gnome-utils/dialog-utils.c & h. - define gnc_new_book_option_display to
display book options dialog in modal mode
gnome/gtkbuilder/assistant-hierarchy.glade - add notification about book
options to currency page
gnome/assistant-hierarchy.c - add ability to set book option initialized
from preferences value for new books by using functions gnc_is_new_book
and gnc_new_book_option_display
11. Modify Import QIF process to recognize a new-book situation and allow setting
of book options during first import into a new book; also follow book option
setting for num source in importing number whether new book or not:
import-export/qif-import/assistant-qif-import.glade - add notification about
book options to currency page
import-export/qif-import/assistant-qif-import.c - using function
gnc_is_new_book to identify 'new book' situation and set flag; add
logic to handle 'new-book' situation by calling
gnc_new_book_option_display function
import-export/qif-import/qif-to-gnc.scm - use 'gnc_set_num_action' function
to import number to correct field based on book option
12. Modify Import OFX/QFX process to recognize a new-book situation and allow setting
of book options during first import into a new book; also follow book option
setting for num source in importing number whether new book or not:
import-export/ofx/gnc-ofx-import.c - use 'gnc_set_num_action' function to import
number based on book option; identify 'new book' situation using function
gnc_is_new_book and set flag; add logic to handle 'new-book' situation
by raising book options dialog by calling gnc_new_book_option_display
function
import-export/import-backend.c - use 'gnc_get_num_action' function to
retrieve number from transactions to be matched based on book option
13. Modify Import AqBanking process to recognize a new-book situation and allow
setting of book options during first import into a new book; also follow
book option setting for num source in importing number:
import-export/aqbanking/gnc-file-aqb-import.c - identify 'new book'
situation using function gnc_is_new_book and handle by raising book
options dialog by calling gnc_new_book_option_display function
import-export/aqbanking/gnc-ab-utils.c - use 'gnc_set_num_action' function
to set number based on book option
14. Modify Import Transactions from CSV process to recognize a new-book situation
and allow setting of book options during first import into a new book; also
follow book option setting for num source in importing number whether new
book or not:
import-export/csv-import/assistant-csv-trans-import.glade - modify
commments to alert user of raising book options dialog in cases of csv
import into a new book
import-export/csv-import/gnc-csv-model.c & h. - use 'gnc_set_num_action'
function to import number based on book option
import-export/csv-import/assistant-csv-trans-import.c - add logic to handle
'new-book' situation by raising book options dialog by calling
gnc_new_book_option_display function; identify 'new book' situation
using function gnc_is_new_book and set flag
15. Modify Import Accounts from CSV process to recognize a new-book situation
and allow setting of book options during first import into a new book
import-export/csv-import/assistant-csv-account-import.c & .h - add logic to
handle 'new-book' situation by raising book options dialog by calling
gnc_new_book_option_display function; identify 'new book' situation
using function gnc_is_new_book and set flag
16. Modify Export Transactions to CSV process to follow book option setting
for num source in exporting transactions:
import-export/csv-export/csv-transactions-export.c - modify headings to
reflect num-source book option and use 'gnc_get_num_action' function
to retrieve number and action
17. Modify register reporting to reflect book option setting for num source:
gnome/gnc-plugin-page-register.c - determine and pass along ledger-type?
argument to gnc:register-report-create function
gnome/gnc-plugin-page-register2.c - determine and pass along ledger-type?
argument to gnc:register-report-create function
report/standard-reports/standard-reports.scm - add ledger-type? argument
to gnc:register-report-create function; pass it along to
gnc:register-report-create-internal function
report/standard-reports/register.scm - add ledger-type? argument to
gnc:register-report-create-internal function; use 'gnc-get-num-action'
function in place of xaccTransGetNum and 'gnc-get-action-num' function
in place of xaccSplitGetAction and modify report headings and option
text accordingly
18. Modify all places that use xaccTransSetNum and/or xaccSplitSetAction to use
'gnc_set_num_action' function to set number based on book option except
engine/Transaction.c & .h, engine/test-core/test-engine-stuff.c,
engine/Split.c & .h, engine/test/utest-Split.c, engine/engine-helpers.c & .h,
engine/engine-interface.scm, backend/xml/gnc-transaction-xml-v2.c,
backend/xml/io-gncxml-v1.c, import-export/log-replay/gnc-log-replay.c:
engine/gncOwner.c - use 'gnc_set_num_action' function to set number based
on book option
engine/gncInvoice.c - use 'gnc_set_num_action' function to set number based
on book option
engine/SchedXaction.c - use 'gnc_set_num_action' function to set number and
action
engine/cap-gains.c - use 'gnc_set_num_action' function to set split-action
gnome-utils/dialog-transfer.c - use 'gnc_set_num_action' function to set
number based on book option
gnome-utils/gnc-tree-view-split-reg.c - use 'gnc_set_num_action' function
to set number/action based on book option
gnome/assistant-stock-split.c - use 'gnc_set_num_action' function to set
split-action
19. Modify all places that use xaccTransGetNum and/or xaccSplitGetAction to use
'gnc_get_num_action' or 'gnc_get_action_num' functions to get number based
on book option except engine/Transaction.c & .h,
engine/test-core/test-engine-stuff.c, engine/Split.c & h.,
engine/test/utest-Split.c, engine/engine-helpers.c,
engine/engine-interface.scm, backend/xml/gnc-transaction-xml-v2.c,
backend/xml/test/test-xml-transaction.c:
gnome/dialog-lot-viewer.c - use 'gnc_get_num_action' function to retrieve
number based on book option
gnome/dialog-sx-from-trans.c - use 'gnc_get_num_action' function to
retrieve number and action
gnome/dialog-print-check.c - use 'gnc_get_num_action' function to
retrieve number and 'gnc_get_action_num' function to retrieve action
register/ledger-core/split-register-model.c - use 'gnc_get_num_action'
function to retrieve number based on book option
register/ledger-core/split-register-load.c - use 'gnc_get_num_action'
function to retrieve number based on book option
register/ledger-core/split-register-control.c - use 'gnc_get_num_action'
function to retrieve action
register/ledger-core/split-register.c - use 'gnc_get_num_action'
function to retrieve transaction-num
engine/cap-gains.c - use 'gnc_get_num_action' function to get split-action
gnome-utils/gnc-tree-view-split-reg.c - use 'gnc_get_num_action' function
to retrieve number and 'gnc_get_action_num' function to retrieve action
gnome-utils/gnc-tree-model-split-reg.c - use 'gnc_get_num_action' function
to retrieve transaction-number but may not be getting what is expected
if book option to use split-action for 'num' is set
report/locale-specific/us/taxtxf.scm - use 'gnc-get-num-action' function in
place of xaccTransGetNum and 'gnc-get-action-num' function in place of
xaccSplitGetAction and modify report headings and option text accordingly
report/standard-reports/transaction.scm - use 'gnc-get-num-action' function
in place of xaccTransGetNum, adjust sorting based on book option and
modify report headings and option text accordingly; add 'SPLIT-ACTION'
as a term for sorting queries
report/business-reports/customer-summary.scm - use 'gnc-get-num-action'
function in place of xaccTransGetNum
report/business-reports/owner-report.scm - use 'gnc-get-num-action'
function in place of xaccTransGetNum
report/business-reports/job-report.scm - use 'gnc-get-num-action' function
in place of xaccTransGetNum
business/business-gnome/dialog-payment.c - use 'gnc_get_num_action'
function to retrieve number based on book option
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@22681 57a11ea4-9604-0410-9ed3-97b8803252fd
2012-12-22 00:00:54 -06:00
|
|
|
if (actna && actnb) /* split action string, if not NULL */
|
|
|
|
{
|
2021-06-08 11:49:46 -05:00
|
|
|
retval = order_by_int64_or_string (actna, actnb);
|
Implement a Book Option to give users the choice to use the transaction number field (default and current behaviour) or, alternatively, the split action field of the anchor split for 'Num' column on registers, reports, import and export, where applicable. The difference between the two is that with the default, the same 'Num' is displayed for a given transaction regardless of what register it is viewed in and with the new option, a different 'Num' can be entered/displayed for a given transaction in each register it is viewed in. In both cases, the 'next number logic' of the 'Num' cell is based on the account of the register the transaction is entered/viewed from but in one case it fills the transaction number, in the other, it fills the split action field of the anchor split (with the transaction number field displayed in the register cell labeled 'T-Num'). In both cases, both fields are visible and can be used as free-form text in double-line mode for any value the user wants. If the new option is not selected, there should be no change in Gnucash's behaviour with the exception of displaying the book options dialog in 'new book' situations.
The changes made are:
1. Implement the new book option to select source for 'num' cell:
libqof/qof/qofbookslots.h - define num source option
engine/engine.i - define 'NUM-FIELD-SOURCE' as an option name and
'SPLIT-ACTION' as a term for sorting queries
app-utils/business-prefs.scm - define book option for num-field-source
app-utils/app-utils.scm - define and export book option for num-field-source
2. Implement functions to get book option setting and to test:
libqof/qof/qofbook.c & .h - define function to get number source book option
libqof/qof/test/test-qofbook.c - test function to get number source book option
3. Implement a notification mechanism for book option changes:
engine/engine-helpers.c & .h - define functions to register callbacks,
define function to remove callbacks and
define function to initiate callbacks on book num-source option changes
core-utils/gnc-features.c & .h - define feature for num-source
app-utils/gnc-ui-util.c & .h - define gnc_book_option_num_field_source_change_cb;
include setting of feature flag on initial use
gnome-utils/gnc-main-window.c - change name of gnc_options_dialog_apply_cb
function to gnc_book_options_dialog_apply_cb and adjust function to
call function gnc_book_option_num_field_source_change_cb when book
option for num-field-source changes; change name of
gnc_options_dialog_close_cb to gnc_book_options_dialog_close_cb
4. Implement 'help' button response on Book Option Dialog:
gnome-utils/gnc-ui.h - define "book-options" section of help manual
gnome-utils/gnc-gnome-utils.c & .h - implement Book Options help callback
gnome-utils/gnc-main-window.c - use gnc_options_dialog_set_book_options_help_cb
to make help button active
5. Implement utility functions to get/set number/action based on book option:
engine/engine-helpers.c & .h - define 'gnc_get_num_action' function
define 'gnc_get_action_num' function
define 'gnc_set_num_action' function
engine/engine.i - make get/set num/action functions available to guile &
allow #f to be used in place of NULL from guile
engine/Transaction.h - add reference to utility functions in comments to
xaccTransSetNum and xaccTransGetNum functions
engine/Split.h - add reference to utility functions in comments to
xaccSplitSetAction and xaccSplitGetAction functions
6. Implement register use of num source book option; for General, Income and Search
Ledgers, since there is no anchor split, always show tran-num in transaction
cursor, but vary label to correspond to book option:
register/ledger-core/split-register.h - define TNUM_CELL
define CURSOR_DOUBLE_LEDGER_NUM_ACTN cursor name to use TNUM_CELL
define CURSOR_DOUBLE_JOURNAL_NUM_ACTN cursor name to use TNUM_CELL
add boolean to split_reg structure to hold num source book option
register/ledger-core/split-register-layout.c -
add logic to define and set up new ledger/journal cursors with TNUM_CELLs
add logic to add the new cursors to a layout
add logic to add TNUM_CELL to a layout
register/ledger-core/split-register-model.c -
define function to get TNUM_CELL label
add logic to recognize ledger/journal cursors with TNUM_CELL
modify function to get NUM_CELL value based on book option and register
type
define function to get TNUM_CELL value
adjust num help text to reflect book option choice
define function to get TNUM_CELL help
modify function to get action help to reflect book option choice
set up handlers for TNUM_CELL
register/ledger-core/split-register-model-save.c -
use 'gnc_set_num_action' function to set num/action for NUM_CELL based
on book option
define function to save TNUM_CELL using 'gnc_set_num_action' function
set save handler for TNUM_CELL
register/ledger-core/split-register-util.c -
modify logic to recognize ledger/journal cursors with tnum_cell
register/ledger-core/split-register.c -
define split_register_book_option_changed function
register split_register_book_option_changed function in register init
initialize register structure setting to book option
remove split_register_book_option_changed function in register destroy
modify gnc_split_register_save_to_scm to handle TNUM_CELL
7. Enhance transaction copy/duplicate logic to accommodate new book option:
gnome/gtkbuilder/gnc-plugin-page-register.glade -
add widgets to handle trans number and/or split action based on book option
gnome-utils/dialog-dup-trans.c & .h -
add capability to display and handle 'Num' field according to book option
gnome/gnc-plugin-page-register.c - define gnc_find_register_by_account
register/ledger-core/split-register.c -
modify gnc_split_register_duplicate_current to accomodate book option
setting
register/ledger-core/Makefile.am - add GNOME_CFLAGS
register/ledger-core/test/Makefile.am - add libgnc-gnome.la
8. Adjust register sort and sort labels related to Num/Action radio buttons to
correspond to book option for clarity:
gnome/gnc-plugin-page-register.c -
define gnc_plugin_page_register_sort_book_option_changed to adjust labels
register function in gnc_plugin_page_register_cmd_view_sort_by
and save num and action radio widgets
initialize radio widget labels to correspond to book option
remove function in gnc_plugin_page_register_sort_response_cb
and clear num and action radio widgets
gnome/gnc-split-reg.c & h. -
create versions of gnc_split_reg_sort and gnc_split_reg_set_sort to force
a re-sort to be used when num-source book option changes
engine/Transaction.c & .h -
modify default sort to use split action in place of tran num per book
option if called from xaccSplitOrder
engine/Split.c -
modify xaccSplitOrder to call xaccTransOrder_num_action to switch use of
split action and tran num per book option
engine/test/utest-Split.c -
modify test_xaccSplitOrder to call xaccTransOrder_num_action based on
book option
9. Adjust transaction find labels related to Num/Action to correspond to book option
for clarity:
gnome/dialog-find-transactions.c - adjust labels in search criteria based
on book option
gnome-search/dialog-search.c -
define gnc_search_dialog_book_option_changed to adjust labels
register function in gnc_search_dialog_init_widgets when searching
for splits
remove function in gnc_search_dialog_close_cb if registered
10. Modify new file process to allow setting of num-source (actually, all) book
option(s) during New Account Hierarchy Setup:
gnome-utils/gtkbuilder/dialog-preferences.glade - add a user preference for
the default setting for 'num-source' for new books
core-utils/gnc-gconf-utils.h - define KEY_NUM_SOURCE
gnome-utils/gnc-gnome-utils.c & h. -
define gnc_options_dialog_set_new_book_option_values to retrieve
preference values
gnome-utils/dialog-options.c & .h - define gnc_options_dialog_new_modal to
surpress apply button
gnome-utils/gnc-main-window.c - define function gnc_book_options_dialog_cb
with arguments so that the window can be called in modal mode and the
title changed and return dialog widget; call gnc_options_dialog_new_modal
instead of gnc_options_dialog_new; call this function from
gnc_main_window_cmd_file_properties with new arguments; for modal mode,
call gnc-options-dialog-set-new-book-option-values to initialize values
from preferences
app-utils/gnc-ui-util.c & h. - create function gnc_is_new_book for
determining when a new book is being created
gnome-utils/dialog-utils.c & h. - define gnc_new_book_option_display to
display book options dialog in modal mode
gnome/gtkbuilder/assistant-hierarchy.glade - add notification about book
options to currency page
gnome/assistant-hierarchy.c - add ability to set book option initialized
from preferences value for new books by using functions gnc_is_new_book
and gnc_new_book_option_display
11. Modify Import QIF process to recognize a new-book situation and allow setting
of book options during first import into a new book; also follow book option
setting for num source in importing number whether new book or not:
import-export/qif-import/assistant-qif-import.glade - add notification about
book options to currency page
import-export/qif-import/assistant-qif-import.c - using function
gnc_is_new_book to identify 'new book' situation and set flag; add
logic to handle 'new-book' situation by calling
gnc_new_book_option_display function
import-export/qif-import/qif-to-gnc.scm - use 'gnc_set_num_action' function
to import number to correct field based on book option
12. Modify Import OFX/QFX process to recognize a new-book situation and allow setting
of book options during first import into a new book; also follow book option
setting for num source in importing number whether new book or not:
import-export/ofx/gnc-ofx-import.c - use 'gnc_set_num_action' function to import
number based on book option; identify 'new book' situation using function
gnc_is_new_book and set flag; add logic to handle 'new-book' situation
by raising book options dialog by calling gnc_new_book_option_display
function
import-export/import-backend.c - use 'gnc_get_num_action' function to
retrieve number from transactions to be matched based on book option
13. Modify Import AqBanking process to recognize a new-book situation and allow
setting of book options during first import into a new book; also follow
book option setting for num source in importing number:
import-export/aqbanking/gnc-file-aqb-import.c - identify 'new book'
situation using function gnc_is_new_book and handle by raising book
options dialog by calling gnc_new_book_option_display function
import-export/aqbanking/gnc-ab-utils.c - use 'gnc_set_num_action' function
to set number based on book option
14. Modify Import Transactions from CSV process to recognize a new-book situation
and allow setting of book options during first import into a new book; also
follow book option setting for num source in importing number whether new
book or not:
import-export/csv-import/assistant-csv-trans-import.glade - modify
commments to alert user of raising book options dialog in cases of csv
import into a new book
import-export/csv-import/gnc-csv-model.c & h. - use 'gnc_set_num_action'
function to import number based on book option
import-export/csv-import/assistant-csv-trans-import.c - add logic to handle
'new-book' situation by raising book options dialog by calling
gnc_new_book_option_display function; identify 'new book' situation
using function gnc_is_new_book and set flag
15. Modify Import Accounts from CSV process to recognize a new-book situation
and allow setting of book options during first import into a new book
import-export/csv-import/assistant-csv-account-import.c & .h - add logic to
handle 'new-book' situation by raising book options dialog by calling
gnc_new_book_option_display function; identify 'new book' situation
using function gnc_is_new_book and set flag
16. Modify Export Transactions to CSV process to follow book option setting
for num source in exporting transactions:
import-export/csv-export/csv-transactions-export.c - modify headings to
reflect num-source book option and use 'gnc_get_num_action' function
to retrieve number and action
17. Modify register reporting to reflect book option setting for num source:
gnome/gnc-plugin-page-register.c - determine and pass along ledger-type?
argument to gnc:register-report-create function
gnome/gnc-plugin-page-register2.c - determine and pass along ledger-type?
argument to gnc:register-report-create function
report/standard-reports/standard-reports.scm - add ledger-type? argument
to gnc:register-report-create function; pass it along to
gnc:register-report-create-internal function
report/standard-reports/register.scm - add ledger-type? argument to
gnc:register-report-create-internal function; use 'gnc-get-num-action'
function in place of xaccTransGetNum and 'gnc-get-action-num' function
in place of xaccSplitGetAction and modify report headings and option
text accordingly
18. Modify all places that use xaccTransSetNum and/or xaccSplitSetAction to use
'gnc_set_num_action' function to set number based on book option except
engine/Transaction.c & .h, engine/test-core/test-engine-stuff.c,
engine/Split.c & .h, engine/test/utest-Split.c, engine/engine-helpers.c & .h,
engine/engine-interface.scm, backend/xml/gnc-transaction-xml-v2.c,
backend/xml/io-gncxml-v1.c, import-export/log-replay/gnc-log-replay.c:
engine/gncOwner.c - use 'gnc_set_num_action' function to set number based
on book option
engine/gncInvoice.c - use 'gnc_set_num_action' function to set number based
on book option
engine/SchedXaction.c - use 'gnc_set_num_action' function to set number and
action
engine/cap-gains.c - use 'gnc_set_num_action' function to set split-action
gnome-utils/dialog-transfer.c - use 'gnc_set_num_action' function to set
number based on book option
gnome-utils/gnc-tree-view-split-reg.c - use 'gnc_set_num_action' function
to set number/action based on book option
gnome/assistant-stock-split.c - use 'gnc_set_num_action' function to set
split-action
19. Modify all places that use xaccTransGetNum and/or xaccSplitGetAction to use
'gnc_get_num_action' or 'gnc_get_action_num' functions to get number based
on book option except engine/Transaction.c & .h,
engine/test-core/test-engine-stuff.c, engine/Split.c & h.,
engine/test/utest-Split.c, engine/engine-helpers.c,
engine/engine-interface.scm, backend/xml/gnc-transaction-xml-v2.c,
backend/xml/test/test-xml-transaction.c:
gnome/dialog-lot-viewer.c - use 'gnc_get_num_action' function to retrieve
number based on book option
gnome/dialog-sx-from-trans.c - use 'gnc_get_num_action' function to
retrieve number and action
gnome/dialog-print-check.c - use 'gnc_get_num_action' function to
retrieve number and 'gnc_get_action_num' function to retrieve action
register/ledger-core/split-register-model.c - use 'gnc_get_num_action'
function to retrieve number based on book option
register/ledger-core/split-register-load.c - use 'gnc_get_num_action'
function to retrieve number based on book option
register/ledger-core/split-register-control.c - use 'gnc_get_num_action'
function to retrieve action
register/ledger-core/split-register.c - use 'gnc_get_num_action'
function to retrieve transaction-num
engine/cap-gains.c - use 'gnc_get_num_action' function to get split-action
gnome-utils/gnc-tree-view-split-reg.c - use 'gnc_get_num_action' function
to retrieve number and 'gnc_get_action_num' function to retrieve action
gnome-utils/gnc-tree-model-split-reg.c - use 'gnc_get_num_action' function
to retrieve transaction-number but may not be getting what is expected
if book option to use split-action for 'num' is set
report/locale-specific/us/taxtxf.scm - use 'gnc-get-num-action' function in
place of xaccTransGetNum and 'gnc-get-action-num' function in place of
xaccSplitGetAction and modify report headings and option text accordingly
report/standard-reports/transaction.scm - use 'gnc-get-num-action' function
in place of xaccTransGetNum, adjust sorting based on book option and
modify report headings and option text accordingly; add 'SPLIT-ACTION'
as a term for sorting queries
report/business-reports/customer-summary.scm - use 'gnc-get-num-action'
function in place of xaccTransGetNum
report/business-reports/owner-report.scm - use 'gnc-get-num-action'
function in place of xaccTransGetNum
report/business-reports/job-report.scm - use 'gnc-get-num-action' function
in place of xaccTransGetNum
business/business-gnome/dialog-payment.c - use 'gnc_get_num_action'
function to retrieve number based on book option
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@22681 57a11ea4-9604-0410-9ed3-97b8803252fd
2012-12-22 00:00:54 -06:00
|
|
|
}
|
|
|
|
else /* else transaction num string */
|
|
|
|
{
|
2021-06-08 11:49:46 -05:00
|
|
|
retval = order_by_int64_or_string (ta->num, tb->num);
|
Implement a Book Option to give users the choice to use the transaction number field (default and current behaviour) or, alternatively, the split action field of the anchor split for 'Num' column on registers, reports, import and export, where applicable. The difference between the two is that with the default, the same 'Num' is displayed for a given transaction regardless of what register it is viewed in and with the new option, a different 'Num' can be entered/displayed for a given transaction in each register it is viewed in. In both cases, the 'next number logic' of the 'Num' cell is based on the account of the register the transaction is entered/viewed from but in one case it fills the transaction number, in the other, it fills the split action field of the anchor split (with the transaction number field displayed in the register cell labeled 'T-Num'). In both cases, both fields are visible and can be used as free-form text in double-line mode for any value the user wants. If the new option is not selected, there should be no change in Gnucash's behaviour with the exception of displaying the book options dialog in 'new book' situations.
The changes made are:
1. Implement the new book option to select source for 'num' cell:
libqof/qof/qofbookslots.h - define num source option
engine/engine.i - define 'NUM-FIELD-SOURCE' as an option name and
'SPLIT-ACTION' as a term for sorting queries
app-utils/business-prefs.scm - define book option for num-field-source
app-utils/app-utils.scm - define and export book option for num-field-source
2. Implement functions to get book option setting and to test:
libqof/qof/qofbook.c & .h - define function to get number source book option
libqof/qof/test/test-qofbook.c - test function to get number source book option
3. Implement a notification mechanism for book option changes:
engine/engine-helpers.c & .h - define functions to register callbacks,
define function to remove callbacks and
define function to initiate callbacks on book num-source option changes
core-utils/gnc-features.c & .h - define feature for num-source
app-utils/gnc-ui-util.c & .h - define gnc_book_option_num_field_source_change_cb;
include setting of feature flag on initial use
gnome-utils/gnc-main-window.c - change name of gnc_options_dialog_apply_cb
function to gnc_book_options_dialog_apply_cb and adjust function to
call function gnc_book_option_num_field_source_change_cb when book
option for num-field-source changes; change name of
gnc_options_dialog_close_cb to gnc_book_options_dialog_close_cb
4. Implement 'help' button response on Book Option Dialog:
gnome-utils/gnc-ui.h - define "book-options" section of help manual
gnome-utils/gnc-gnome-utils.c & .h - implement Book Options help callback
gnome-utils/gnc-main-window.c - use gnc_options_dialog_set_book_options_help_cb
to make help button active
5. Implement utility functions to get/set number/action based on book option:
engine/engine-helpers.c & .h - define 'gnc_get_num_action' function
define 'gnc_get_action_num' function
define 'gnc_set_num_action' function
engine/engine.i - make get/set num/action functions available to guile &
allow #f to be used in place of NULL from guile
engine/Transaction.h - add reference to utility functions in comments to
xaccTransSetNum and xaccTransGetNum functions
engine/Split.h - add reference to utility functions in comments to
xaccSplitSetAction and xaccSplitGetAction functions
6. Implement register use of num source book option; for General, Income and Search
Ledgers, since there is no anchor split, always show tran-num in transaction
cursor, but vary label to correspond to book option:
register/ledger-core/split-register.h - define TNUM_CELL
define CURSOR_DOUBLE_LEDGER_NUM_ACTN cursor name to use TNUM_CELL
define CURSOR_DOUBLE_JOURNAL_NUM_ACTN cursor name to use TNUM_CELL
add boolean to split_reg structure to hold num source book option
register/ledger-core/split-register-layout.c -
add logic to define and set up new ledger/journal cursors with TNUM_CELLs
add logic to add the new cursors to a layout
add logic to add TNUM_CELL to a layout
register/ledger-core/split-register-model.c -
define function to get TNUM_CELL label
add logic to recognize ledger/journal cursors with TNUM_CELL
modify function to get NUM_CELL value based on book option and register
type
define function to get TNUM_CELL value
adjust num help text to reflect book option choice
define function to get TNUM_CELL help
modify function to get action help to reflect book option choice
set up handlers for TNUM_CELL
register/ledger-core/split-register-model-save.c -
use 'gnc_set_num_action' function to set num/action for NUM_CELL based
on book option
define function to save TNUM_CELL using 'gnc_set_num_action' function
set save handler for TNUM_CELL
register/ledger-core/split-register-util.c -
modify logic to recognize ledger/journal cursors with tnum_cell
register/ledger-core/split-register.c -
define split_register_book_option_changed function
register split_register_book_option_changed function in register init
initialize register structure setting to book option
remove split_register_book_option_changed function in register destroy
modify gnc_split_register_save_to_scm to handle TNUM_CELL
7. Enhance transaction copy/duplicate logic to accommodate new book option:
gnome/gtkbuilder/gnc-plugin-page-register.glade -
add widgets to handle trans number and/or split action based on book option
gnome-utils/dialog-dup-trans.c & .h -
add capability to display and handle 'Num' field according to book option
gnome/gnc-plugin-page-register.c - define gnc_find_register_by_account
register/ledger-core/split-register.c -
modify gnc_split_register_duplicate_current to accomodate book option
setting
register/ledger-core/Makefile.am - add GNOME_CFLAGS
register/ledger-core/test/Makefile.am - add libgnc-gnome.la
8. Adjust register sort and sort labels related to Num/Action radio buttons to
correspond to book option for clarity:
gnome/gnc-plugin-page-register.c -
define gnc_plugin_page_register_sort_book_option_changed to adjust labels
register function in gnc_plugin_page_register_cmd_view_sort_by
and save num and action radio widgets
initialize radio widget labels to correspond to book option
remove function in gnc_plugin_page_register_sort_response_cb
and clear num and action radio widgets
gnome/gnc-split-reg.c & h. -
create versions of gnc_split_reg_sort and gnc_split_reg_set_sort to force
a re-sort to be used when num-source book option changes
engine/Transaction.c & .h -
modify default sort to use split action in place of tran num per book
option if called from xaccSplitOrder
engine/Split.c -
modify xaccSplitOrder to call xaccTransOrder_num_action to switch use of
split action and tran num per book option
engine/test/utest-Split.c -
modify test_xaccSplitOrder to call xaccTransOrder_num_action based on
book option
9. Adjust transaction find labels related to Num/Action to correspond to book option
for clarity:
gnome/dialog-find-transactions.c - adjust labels in search criteria based
on book option
gnome-search/dialog-search.c -
define gnc_search_dialog_book_option_changed to adjust labels
register function in gnc_search_dialog_init_widgets when searching
for splits
remove function in gnc_search_dialog_close_cb if registered
10. Modify new file process to allow setting of num-source (actually, all) book
option(s) during New Account Hierarchy Setup:
gnome-utils/gtkbuilder/dialog-preferences.glade - add a user preference for
the default setting for 'num-source' for new books
core-utils/gnc-gconf-utils.h - define KEY_NUM_SOURCE
gnome-utils/gnc-gnome-utils.c & h. -
define gnc_options_dialog_set_new_book_option_values to retrieve
preference values
gnome-utils/dialog-options.c & .h - define gnc_options_dialog_new_modal to
surpress apply button
gnome-utils/gnc-main-window.c - define function gnc_book_options_dialog_cb
with arguments so that the window can be called in modal mode and the
title changed and return dialog widget; call gnc_options_dialog_new_modal
instead of gnc_options_dialog_new; call this function from
gnc_main_window_cmd_file_properties with new arguments; for modal mode,
call gnc-options-dialog-set-new-book-option-values to initialize values
from preferences
app-utils/gnc-ui-util.c & h. - create function gnc_is_new_book for
determining when a new book is being created
gnome-utils/dialog-utils.c & h. - define gnc_new_book_option_display to
display book options dialog in modal mode
gnome/gtkbuilder/assistant-hierarchy.glade - add notification about book
options to currency page
gnome/assistant-hierarchy.c - add ability to set book option initialized
from preferences value for new books by using functions gnc_is_new_book
and gnc_new_book_option_display
11. Modify Import QIF process to recognize a new-book situation and allow setting
of book options during first import into a new book; also follow book option
setting for num source in importing number whether new book or not:
import-export/qif-import/assistant-qif-import.glade - add notification about
book options to currency page
import-export/qif-import/assistant-qif-import.c - using function
gnc_is_new_book to identify 'new book' situation and set flag; add
logic to handle 'new-book' situation by calling
gnc_new_book_option_display function
import-export/qif-import/qif-to-gnc.scm - use 'gnc_set_num_action' function
to import number to correct field based on book option
12. Modify Import OFX/QFX process to recognize a new-book situation and allow setting
of book options during first import into a new book; also follow book option
setting for num source in importing number whether new book or not:
import-export/ofx/gnc-ofx-import.c - use 'gnc_set_num_action' function to import
number based on book option; identify 'new book' situation using function
gnc_is_new_book and set flag; add logic to handle 'new-book' situation
by raising book options dialog by calling gnc_new_book_option_display
function
import-export/import-backend.c - use 'gnc_get_num_action' function to
retrieve number from transactions to be matched based on book option
13. Modify Import AqBanking process to recognize a new-book situation and allow
setting of book options during first import into a new book; also follow
book option setting for num source in importing number:
import-export/aqbanking/gnc-file-aqb-import.c - identify 'new book'
situation using function gnc_is_new_book and handle by raising book
options dialog by calling gnc_new_book_option_display function
import-export/aqbanking/gnc-ab-utils.c - use 'gnc_set_num_action' function
to set number based on book option
14. Modify Import Transactions from CSV process to recognize a new-book situation
and allow setting of book options during first import into a new book; also
follow book option setting for num source in importing number whether new
book or not:
import-export/csv-import/assistant-csv-trans-import.glade - modify
commments to alert user of raising book options dialog in cases of csv
import into a new book
import-export/csv-import/gnc-csv-model.c & h. - use 'gnc_set_num_action'
function to import number based on book option
import-export/csv-import/assistant-csv-trans-import.c - add logic to handle
'new-book' situation by raising book options dialog by calling
gnc_new_book_option_display function; identify 'new book' situation
using function gnc_is_new_book and set flag
15. Modify Import Accounts from CSV process to recognize a new-book situation
and allow setting of book options during first import into a new book
import-export/csv-import/assistant-csv-account-import.c & .h - add logic to
handle 'new-book' situation by raising book options dialog by calling
gnc_new_book_option_display function; identify 'new book' situation
using function gnc_is_new_book and set flag
16. Modify Export Transactions to CSV process to follow book option setting
for num source in exporting transactions:
import-export/csv-export/csv-transactions-export.c - modify headings to
reflect num-source book option and use 'gnc_get_num_action' function
to retrieve number and action
17. Modify register reporting to reflect book option setting for num source:
gnome/gnc-plugin-page-register.c - determine and pass along ledger-type?
argument to gnc:register-report-create function
gnome/gnc-plugin-page-register2.c - determine and pass along ledger-type?
argument to gnc:register-report-create function
report/standard-reports/standard-reports.scm - add ledger-type? argument
to gnc:register-report-create function; pass it along to
gnc:register-report-create-internal function
report/standard-reports/register.scm - add ledger-type? argument to
gnc:register-report-create-internal function; use 'gnc-get-num-action'
function in place of xaccTransGetNum and 'gnc-get-action-num' function
in place of xaccSplitGetAction and modify report headings and option
text accordingly
18. Modify all places that use xaccTransSetNum and/or xaccSplitSetAction to use
'gnc_set_num_action' function to set number based on book option except
engine/Transaction.c & .h, engine/test-core/test-engine-stuff.c,
engine/Split.c & .h, engine/test/utest-Split.c, engine/engine-helpers.c & .h,
engine/engine-interface.scm, backend/xml/gnc-transaction-xml-v2.c,
backend/xml/io-gncxml-v1.c, import-export/log-replay/gnc-log-replay.c:
engine/gncOwner.c - use 'gnc_set_num_action' function to set number based
on book option
engine/gncInvoice.c - use 'gnc_set_num_action' function to set number based
on book option
engine/SchedXaction.c - use 'gnc_set_num_action' function to set number and
action
engine/cap-gains.c - use 'gnc_set_num_action' function to set split-action
gnome-utils/dialog-transfer.c - use 'gnc_set_num_action' function to set
number based on book option
gnome-utils/gnc-tree-view-split-reg.c - use 'gnc_set_num_action' function
to set number/action based on book option
gnome/assistant-stock-split.c - use 'gnc_set_num_action' function to set
split-action
19. Modify all places that use xaccTransGetNum and/or xaccSplitGetAction to use
'gnc_get_num_action' or 'gnc_get_action_num' functions to get number based
on book option except engine/Transaction.c & .h,
engine/test-core/test-engine-stuff.c, engine/Split.c & h.,
engine/test/utest-Split.c, engine/engine-helpers.c,
engine/engine-interface.scm, backend/xml/gnc-transaction-xml-v2.c,
backend/xml/test/test-xml-transaction.c:
gnome/dialog-lot-viewer.c - use 'gnc_get_num_action' function to retrieve
number based on book option
gnome/dialog-sx-from-trans.c - use 'gnc_get_num_action' function to
retrieve number and action
gnome/dialog-print-check.c - use 'gnc_get_num_action' function to
retrieve number and 'gnc_get_action_num' function to retrieve action
register/ledger-core/split-register-model.c - use 'gnc_get_num_action'
function to retrieve number based on book option
register/ledger-core/split-register-load.c - use 'gnc_get_num_action'
function to retrieve number based on book option
register/ledger-core/split-register-control.c - use 'gnc_get_num_action'
function to retrieve action
register/ledger-core/split-register.c - use 'gnc_get_num_action'
function to retrieve transaction-num
engine/cap-gains.c - use 'gnc_get_num_action' function to get split-action
gnome-utils/gnc-tree-view-split-reg.c - use 'gnc_get_num_action' function
to retrieve number and 'gnc_get_action_num' function to retrieve action
gnome-utils/gnc-tree-model-split-reg.c - use 'gnc_get_num_action' function
to retrieve transaction-number but may not be getting what is expected
if book option to use split-action for 'num' is set
report/locale-specific/us/taxtxf.scm - use 'gnc-get-num-action' function in
place of xaccTransGetNum and 'gnc-get-action-num' function in place of
xaccSplitGetAction and modify report headings and option text accordingly
report/standard-reports/transaction.scm - use 'gnc-get-num-action' function
in place of xaccTransGetNum, adjust sorting based on book option and
modify report headings and option text accordingly; add 'SPLIT-ACTION'
as a term for sorting queries
report/business-reports/customer-summary.scm - use 'gnc-get-num-action'
function in place of xaccTransGetNum
report/business-reports/owner-report.scm - use 'gnc-get-num-action'
function in place of xaccTransGetNum
report/business-reports/job-report.scm - use 'gnc-get-num-action' function
in place of xaccTransGetNum
business/business-gnome/dialog-payment.c - use 'gnc_get_num_action'
function to retrieve number based on book option
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@22681 57a11ea4-9604-0410-9ed3-97b8803252fd
2012-12-22 00:00:54 -06:00
|
|
|
}
|
2021-06-08 11:49:46 -05:00
|
|
|
if (retval)
|
|
|
|
return retval;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2017-12-31 06:37:02 -06:00
|
|
|
if (ta->date_entered != tb->date_entered)
|
|
|
|
return (ta->date_entered > tb->date_entered) - (ta->date_entered < tb->date_entered);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* otherwise, sort on description string */
|
|
|
|
da = ta->description ? ta->description : "";
|
|
|
|
db = tb->description ? tb->description : "";
|
|
|
|
retval = g_utf8_collate (da, db);
|
|
|
|
if (retval)
|
|
|
|
return retval;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* else, sort on guid - keeps sort stable. */
|
|
|
|
return qof_instance_guid_compare(ta, tb);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
2003-09-06 10:02:21 -05:00
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
|
|
|
|
2003-09-01 15:20:52 -05:00
|
|
|
static inline void
|
2017-12-31 06:37:02 -06:00
|
|
|
xaccTransSetDateInternal(Transaction *trans, time64 *dadate, time64 val)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2006-04-22 00:14:48 -05:00
|
|
|
xaccTransBeginEdit(trans);
|
2006-02-06 00:45:25 -06:00
|
|
|
|
2017-08-20 14:31:07 -05:00
|
|
|
#if 0 /* gnc_ctime is expensive so change to 1 only if you need to debug setting
|
|
|
|
* dates. */
|
|
|
|
{
|
2012-12-01 16:44:53 -06:00
|
|
|
time64 secs = (time64) val.tv_sec;
|
|
|
|
gchar *tstr = gnc_ctime (&secs);
|
2013-09-20 16:09:21 -05:00
|
|
|
PINFO ("addr=%p set date to %" G_GUINT64_FORMAT ".%09ld %s\n",
|
2009-01-18 17:43:02 -06:00
|
|
|
trans, val.tv_sec, val.tv_nsec, tstr ? tstr : "(null)");
|
2013-09-20 16:09:21 -05:00
|
|
|
g_free(tstr);
|
2009-01-18 17:43:02 -06:00
|
|
|
}
|
2017-08-20 14:31:07 -05:00
|
|
|
#endif
|
2003-09-01 15:20:52 -05:00
|
|
|
*dadate = val;
|
2006-02-06 11:57:45 -06:00
|
|
|
qof_instance_set_dirty(QOF_INSTANCE(trans));
|
2001-08-07 18:36:04 -05:00
|
|
|
mark_trans(trans);
|
2006-04-22 00:14:48 -05:00
|
|
|
xaccTransCommitEdit(trans);
|
2003-09-01 15:20:52 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Because the date has changed, we need to make sure that each of
|
|
|
|
* the splits is properly ordered in each of their accounts. We
|
|
|
|
* could do that here, simply by reinserting each split into its
|
|
|
|
* account. However, in some ways this is bad behaviour, and it
|
|
|
|
* seems much better/nicer to defer that until the commit phase,
|
|
|
|
* i.e. until the user has called the xaccTransCommitEdit()
|
|
|
|
* routine. So, for now, we are done. */
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2003-09-01 15:20:52 -05:00
|
|
|
static inline void
|
|
|
|
set_gains_date_dirty (Transaction *trans)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2006-03-03 18:10:12 -06:00
|
|
|
FOR_EACH_SPLIT(trans, s->gains |= GAINS_STATUS_DATE_DIRTY);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2002-06-20 19:46:36 -05:00
|
|
|
void
|
2012-12-01 16:44:53 -06:00
|
|
|
xaccTransSetDatePostedSecs (Transaction *trans, time64 secs)
|
2002-06-20 19:46:36 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans) return;
|
2017-12-31 06:37:02 -06:00
|
|
|
xaccTransSetDateInternal(trans, &trans->date_posted, secs);
|
2018-08-02 20:19:15 -05:00
|
|
|
set_gains_date_dirty(trans);
|
2002-06-20 19:46:36 -05:00
|
|
|
}
|
|
|
|
|
2013-06-09 16:32:06 -05:00
|
|
|
void
|
|
|
|
xaccTransSetDatePostedSecsNormalized (Transaction *trans, time64 time)
|
|
|
|
{
|
|
|
|
GDate date;
|
|
|
|
gnc_gdate_set_time64(&date, time);
|
|
|
|
xaccTransSetDatePostedGDate(trans, date);
|
|
|
|
}
|
|
|
|
|
2010-03-17 14:23:40 -05:00
|
|
|
void
|
|
|
|
xaccTransSetDatePostedGDate (Transaction *trans, GDate date)
|
|
|
|
{
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2010-03-17 14:23:40 -05:00
|
|
|
if (!trans) return;
|
|
|
|
|
|
|
|
/* We additionally save this date into a kvp frame to ensure in
|
|
|
|
* the future a date which was set as *date* (without time) can
|
2018-08-02 20:19:15 -05:00
|
|
|
* clearly be distinguished from the time64. */
|
2015-05-08 15:33:40 -05:00
|
|
|
g_value_init (&v, G_TYPE_DATE);
|
|
|
|
g_value_set_boxed (&v, &date);
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE(trans), &v, 1, TRANS_DATE_POSTED);
|
2021-05-30 09:34:30 -05:00
|
|
|
g_value_unset (&v);
|
2013-11-30 19:30:03 -06:00
|
|
|
/* mark dirty and commit handled by SetDateInternal */
|
2010-03-17 14:23:40 -05:00
|
|
|
xaccTransSetDateInternal(trans, &trans->date_posted,
|
2017-12-31 06:37:02 -06:00
|
|
|
gdate_to_time64(date));
|
2010-03-17 14:23:40 -05:00
|
|
|
set_gains_date_dirty (trans);
|
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
void
|
2012-12-01 16:44:53 -06:00
|
|
|
xaccTransSetDateEnteredSecs (Transaction *trans, time64 secs)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans) return;
|
2017-12-31 06:37:02 -06:00
|
|
|
xaccTransSetDateInternal(trans, &trans->date_entered, secs);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
static void
|
2018-08-02 20:19:15 -05:00
|
|
|
qofTransSetDatePosted (Transaction *trans, time64 time)
|
2005-11-01 21:32:36 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans) return;
|
|
|
|
if (!qof_begin_edit(&trans->inst)) return;
|
2018-08-02 20:19:15 -05:00
|
|
|
xaccTransSetDateInternal(trans, &trans->date_posted, time);
|
2010-03-02 15:40:28 -06:00
|
|
|
set_gains_date_dirty(trans);
|
|
|
|
qof_commit_edit(&trans->inst);
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-08-02 20:19:15 -05:00
|
|
|
qofTransSetDateEntered (Transaction *trans, time64 time)
|
2005-11-01 21:32:36 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans) return;
|
|
|
|
if (!qof_begin_edit(&trans->inst)) return;
|
2018-08-02 20:19:15 -05:00
|
|
|
xaccTransSetDateInternal(trans, &trans->date_entered, time);
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_commit_edit(&trans->inst);
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
void
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransSetDate (Transaction *trans, int day, int mon, int year)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-17 14:23:40 -05:00
|
|
|
GDate *date;
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans) return;
|
2010-03-17 14:23:40 -05:00
|
|
|
date = g_date_new_dmy(day, mon, year);
|
2016-12-11 18:32:15 -06:00
|
|
|
if (!g_date_valid(date))
|
|
|
|
{
|
|
|
|
PWARN("Attempted to set invalid date %d-%d-%d; set today's date instead.",
|
|
|
|
year, mon, day);
|
|
|
|
g_free(date);
|
|
|
|
date = gnc_g_date_new_today();
|
|
|
|
}
|
2010-03-17 14:23:40 -05:00
|
|
|
xaccTransSetDatePostedGDate(trans, *date);
|
2016-12-11 18:32:15 -06:00
|
|
|
g_free(date);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2017-12-29 15:07:08 -06:00
|
|
|
void
|
|
|
|
xaccTransSetDateDue (Transaction * trans, time64 time)
|
2001-11-26 22:47:19 -06:00
|
|
|
{
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2017-12-31 06:37:02 -06:00
|
|
|
if (!trans) return;
|
2018-08-02 15:29:47 -05:00
|
|
|
g_value_init (&v, GNC_TYPE_TIME64);
|
|
|
|
g_value_set_boxed (&v, &time);
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransBeginEdit(trans);
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, TRANS_DATE_DUE_KVP);
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_instance_set_dirty(QOF_INSTANCE(trans));
|
2021-05-30 09:34:30 -05:00
|
|
|
g_value_unset (&v);
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransCommitEdit(trans);
|
2001-11-26 22:47:19 -06:00
|
|
|
}
|
|
|
|
|
2001-11-29 22:25:17 -06:00
|
|
|
void
|
|
|
|
xaccTransSetTxnType (Transaction *trans, char type)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
char s[2] = {type, '\0'};
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2010-03-02 15:40:28 -06:00
|
|
|
g_return_if_fail(trans);
|
2015-05-08 15:33:40 -05:00
|
|
|
g_value_init (&v, G_TYPE_STRING);
|
|
|
|
g_value_set_string (&v, s);
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransBeginEdit(trans);
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, TRANS_TXN_TYPE_KVP);
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_instance_set_dirty(QOF_INSTANCE(trans));
|
2021-05-30 09:34:30 -05:00
|
|
|
g_value_unset (&v);
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransCommitEdit(trans);
|
2001-11-29 22:25:17 -06:00
|
|
|
}
|
|
|
|
|
2003-01-01 22:07:58 -06:00
|
|
|
void xaccTransClearReadOnly (Transaction *trans)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (trans)
|
|
|
|
{
|
2006-04-22 00:14:48 -05:00
|
|
|
xaccTransBeginEdit(trans);
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), NULL, 1, TRANS_READ_ONLY_REASON);
|
2006-02-06 11:57:45 -06:00
|
|
|
qof_instance_set_dirty(QOF_INSTANCE(trans));
|
2006-04-22 00:14:48 -05:00
|
|
|
xaccTransCommitEdit(trans);
|
2018-09-09 15:49:52 -05:00
|
|
|
|
2018-09-09 17:02:53 -05:00
|
|
|
g_free (trans->readonly_reason);
|
2018-09-09 15:49:52 -05:00
|
|
|
trans->readonly_reason = NULL;
|
|
|
|
trans->reason_cache_valid = TRUE;
|
2006-02-06 11:57:45 -06:00
|
|
|
}
|
2003-01-01 22:07:58 -06:00
|
|
|
}
|
|
|
|
|
2002-11-05 00:41:45 -06:00
|
|
|
void
|
|
|
|
xaccTransSetReadOnly (Transaction *trans, const char *reason)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (trans && reason)
|
|
|
|
{
|
2017-11-02 14:42:22 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
|
|
|
g_value_init (&v, G_TYPE_STRING);
|
|
|
|
g_value_set_string (&v, reason);
|
2006-04-22 00:14:48 -05:00
|
|
|
xaccTransBeginEdit(trans);
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, TRANS_READ_ONLY_REASON);
|
2006-02-06 11:57:45 -06:00
|
|
|
qof_instance_set_dirty(QOF_INSTANCE(trans));
|
2021-05-30 09:34:30 -05:00
|
|
|
g_value_unset (&v);
|
2006-04-22 00:14:48 -05:00
|
|
|
xaccTransCommitEdit(trans);
|
2018-09-09 15:49:52 -05:00
|
|
|
|
2018-09-09 17:02:53 -05:00
|
|
|
g_free (trans->readonly_reason);
|
2018-09-09 15:49:52 -05:00
|
|
|
trans->readonly_reason = g_strdup (reason);
|
|
|
|
trans->reason_cache_valid = TRUE;
|
2006-02-06 11:57:45 -06:00
|
|
|
}
|
2002-11-05 00:41:45 -06:00
|
|
|
}
|
2001-11-29 22:25:17 -06:00
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
/* QOF does not open the trans before setting a parameter,
|
|
|
|
but the call uses check_open so we cannot use the call directly. */
|
|
|
|
static void
|
|
|
|
qofTransSetNum (Transaction *trans, const char *xnum)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!qof_begin_edit(&trans->inst)) return;
|
|
|
|
xaccTransSetNum(trans, xnum);
|
|
|
|
qof_commit_edit(&trans->inst);
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
void
|
|
|
|
xaccTransSetNum (Transaction *trans, const char *xnum)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans || !xnum) return;
|
|
|
|
xaccTransBeginEdit(trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
CACHE_REPLACE(trans->num, xnum);
|
|
|
|
qof_instance_set_dirty(QOF_INSTANCE(trans));
|
|
|
|
mark_trans(trans); /* Dirty balance of every account in trans */
|
|
|
|
xaccTransCommitEdit(trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
static void
|
|
|
|
qofTransSetDescription (Transaction *trans, const char *desc)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!qof_begin_edit(&trans->inst)) return;
|
|
|
|
xaccTransSetDescription(trans, desc);
|
|
|
|
qof_commit_edit(&trans->inst);
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
void
|
|
|
|
xaccTransSetDescription (Transaction *trans, const char *desc)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans || !desc) return;
|
|
|
|
xaccTransBeginEdit(trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
CACHE_REPLACE(trans->description, desc);
|
|
|
|
qof_instance_set_dirty(QOF_INSTANCE(trans));
|
|
|
|
xaccTransCommitEdit(trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2013-11-15 16:02:34 -06:00
|
|
|
void
|
2020-08-15 19:05:21 -05:00
|
|
|
xaccTransSetDocLink (Transaction *trans, const char *doclink)
|
2013-11-15 16:02:34 -06:00
|
|
|
{
|
2020-08-15 19:05:21 -05:00
|
|
|
if (!trans || !doclink) return;
|
2013-11-15 16:02:34 -06:00
|
|
|
xaccTransBeginEdit(trans);
|
2020-08-15 19:05:21 -05:00
|
|
|
if (g_strcmp0 (doclink, "") == 0)
|
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), NULL, 1, doclink_uri_str);
|
2018-11-15 08:01:27 -06:00
|
|
|
else
|
|
|
|
{
|
|
|
|
GValue v = G_VALUE_INIT;
|
|
|
|
g_value_init (&v, G_TYPE_STRING);
|
2020-08-15 19:05:21 -05:00
|
|
|
g_value_set_string (&v, doclink);
|
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, doclink_uri_str);
|
2021-05-30 09:34:30 -05:00
|
|
|
g_value_unset (&v);
|
2018-11-15 08:01:27 -06:00
|
|
|
}
|
2013-11-15 16:02:34 -06:00
|
|
|
qof_instance_set_dirty(QOF_INSTANCE(trans));
|
|
|
|
xaccTransCommitEdit(trans);
|
|
|
|
}
|
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
static void
|
|
|
|
qofTransSetNotes (Transaction *trans, const char *notes)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!qof_begin_edit(&trans->inst)) return;
|
|
|
|
xaccTransSetNotes(trans, notes);
|
|
|
|
qof_commit_edit(&trans->inst);
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
void
|
|
|
|
xaccTransSetNotes (Transaction *trans, const char *notes)
|
|
|
|
{
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans || !notes) return;
|
2015-05-08 15:33:40 -05:00
|
|
|
g_value_init (&v, G_TYPE_STRING);
|
|
|
|
g_value_set_string (&v, notes);
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransBeginEdit(trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, trans_notes_str);
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_instance_set_dirty(QOF_INSTANCE(trans));
|
2021-05-30 09:34:30 -05:00
|
|
|
g_value_unset (&v);
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransCommitEdit(trans);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2010-12-15 20:11:53 -06:00
|
|
|
void
|
|
|
|
xaccTransSetIsClosingTxn (Transaction *trans, gboolean is_closing)
|
|
|
|
{
|
|
|
|
if (!trans) return;
|
|
|
|
xaccTransBeginEdit(trans);
|
|
|
|
|
|
|
|
if (is_closing)
|
2015-05-08 15:33:40 -05:00
|
|
|
{
|
2017-11-02 14:42:22 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
|
|
|
g_value_init (&v, G_TYPE_INT64);
|
|
|
|
g_value_set_int64 (&v, 1);
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, trans_is_closing_str);
|
2021-05-30 09:34:30 -05:00
|
|
|
g_value_unset (&v);
|
2018-12-31 07:48:26 -06:00
|
|
|
trans->isClosingTxn_cached = 1;
|
2015-05-08 15:33:40 -05:00
|
|
|
}
|
2010-12-15 20:11:53 -06:00
|
|
|
else
|
2018-12-31 07:48:26 -06:00
|
|
|
{
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), NULL, 1, trans_is_closing_str);
|
2018-12-31 07:48:26 -06:00
|
|
|
trans->isClosingTxn_cached = 0;
|
|
|
|
}
|
2010-12-15 20:11:53 -06:00
|
|
|
qof_instance_set_dirty(QOF_INSTANCE(trans));
|
|
|
|
xaccTransCommitEdit(trans);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
|
|
|
|
|
|
|
Split *
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransGetSplit (const Transaction *trans, int i)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2006-03-04 22:14:38 -06:00
|
|
|
int j = 0;
|
|
|
|
if (!trans || i < 0) return NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2006-03-04 22:14:38 -06:00
|
|
|
FOR_EACH_SPLIT(trans, { if (i == j) return s; j++; });
|
|
|
|
return NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2006-03-07 23:47:36 -06:00
|
|
|
int
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransGetSplitIndex(const Transaction *trans, const Split *split)
|
2006-03-07 23:47:36 -06:00
|
|
|
{
|
|
|
|
int j = 0;
|
|
|
|
g_return_val_if_fail(trans && split, -1);
|
|
|
|
|
|
|
|
FOR_EACH_SPLIT(trans, { if (s == split) return j; j++; });
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2001-10-31 09:25:46 -06:00
|
|
|
SplitList *
|
2002-12-07 07:05:45 -06:00
|
|
|
xaccTransGetSplitList (const Transaction *trans)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
return trans ? trans->splits : NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2017-11-13 12:15:04 -06:00
|
|
|
SplitList *
|
|
|
|
xaccTransGetPaymentAcctSplitList (const Transaction *trans)
|
|
|
|
{
|
|
|
|
GList *pay_splits = NULL;
|
|
|
|
FOR_EACH_SPLIT (trans,
|
|
|
|
const Account *account = xaccSplitGetAccount(s);
|
|
|
|
if (account && gncBusinessIsPaymentAcctType(xaccAccountGetType(account)))
|
|
|
|
pay_splits = g_list_prepend (pay_splits, s);
|
|
|
|
);
|
|
|
|
|
|
|
|
pay_splits = g_list_reverse (pay_splits);
|
|
|
|
return pay_splits;
|
|
|
|
}
|
|
|
|
|
|
|
|
SplitList *
|
|
|
|
xaccTransGetAPARAcctSplitList (const Transaction *trans, gboolean strict)
|
|
|
|
{
|
|
|
|
GList *apar_splits = NULL;
|
2020-08-16 04:54:24 -05:00
|
|
|
if (!trans) return NULL;
|
|
|
|
|
2017-11-13 12:15:04 -06:00
|
|
|
FOR_EACH_SPLIT (trans,
|
|
|
|
const Account *account = xaccSplitGetAccount(s);
|
|
|
|
if (account && xaccAccountIsAPARType(xaccAccountGetType(account)))
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!strict)
|
|
|
|
apar_splits = g_list_prepend (apar_splits, s);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GncOwner owner;
|
|
|
|
GNCLot *lot = xaccSplitGetLot(s);
|
|
|
|
if (lot &&
|
|
|
|
(gncInvoiceGetInvoiceFromLot (lot) ||
|
|
|
|
gncOwnerGetOwnerFromLot (lot, &owner)))
|
|
|
|
apar_splits = g_list_prepend (apar_splits, s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
apar_splits = g_list_reverse (apar_splits);
|
|
|
|
return apar_splits;
|
|
|
|
}
|
|
|
|
|
2016-03-25 06:10:10 -05:00
|
|
|
Split *xaccTransGetFirstPaymentAcctSplit(const Transaction *trans)
|
|
|
|
{
|
|
|
|
FOR_EACH_SPLIT (trans,
|
|
|
|
const Account *account = xaccSplitGetAccount(s);
|
2017-11-13 12:15:04 -06:00
|
|
|
if (account && gncBusinessIsPaymentAcctType(xaccAccountGetType(account)))
|
2016-03-25 06:10:10 -05:00
|
|
|
return s;
|
|
|
|
);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-11-13 12:15:04 -06:00
|
|
|
Split *xaccTransGetFirstAPARAcctSplit (const Transaction *trans, gboolean strict)
|
2016-03-25 06:10:10 -05:00
|
|
|
{
|
|
|
|
FOR_EACH_SPLIT (trans,
|
|
|
|
const Account *account = xaccSplitGetAccount(s);
|
2017-11-13 12:15:04 -06:00
|
|
|
if (account && xaccAccountIsAPARType(xaccAccountGetType(account)))
|
|
|
|
{
|
|
|
|
GNCLot *lot;
|
|
|
|
GncOwner owner;
|
|
|
|
|
|
|
|
if (!strict)
|
|
|
|
return s;
|
|
|
|
|
|
|
|
lot = xaccSplitGetLot(s);
|
|
|
|
if (lot &&
|
|
|
|
(gncInvoiceGetInvoiceFromLot (lot) ||
|
|
|
|
gncOwnerGetOwnerFromLot (lot, &owner)))
|
|
|
|
return s;
|
|
|
|
}
|
2016-03-25 06:10:10 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-03-03 18:10:12 -06:00
|
|
|
int
|
|
|
|
xaccTransCountSplits (const Transaction *trans)
|
|
|
|
{
|
2006-03-04 22:14:38 -06:00
|
|
|
gint i = 0;
|
2018-01-30 16:33:02 -06:00
|
|
|
g_return_val_if_fail (trans != NULL, 0);
|
2006-03-04 22:14:38 -06:00
|
|
|
FOR_EACH_SPLIT(trans, i++);
|
|
|
|
return i;
|
2006-03-03 18:10:12 -06:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
const char *
|
2002-12-07 07:05:45 -06:00
|
|
|
xaccTransGetNum (const Transaction *trans)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
return trans ? trans->num : NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
const char *
|
2002-12-07 07:05:45 -06:00
|
|
|
xaccTransGetDescription (const Transaction *trans)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
return trans ? trans->description : NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2013-11-15 16:02:34 -06:00
|
|
|
const char *
|
2020-08-15 19:05:21 -05:00
|
|
|
xaccTransGetDocLink (const Transaction *trans)
|
2013-11-15 16:02:34 -06:00
|
|
|
{
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
|
|
|
if (!trans) return NULL;
|
2020-08-15 19:05:21 -05:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, doclink_uri_str);
|
2015-06-04 15:29:01 -05:00
|
|
|
if (G_VALUE_HOLDS_STRING (&v))
|
|
|
|
return g_value_get_string (&v);
|
|
|
|
return NULL;
|
2013-11-15 16:02:34 -06:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
const char *
|
2002-12-07 07:05:45 -06:00
|
|
|
xaccTransGetNotes (const Transaction *trans)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
|
|
|
if (!trans) return NULL;
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, trans_notes_str);
|
2015-06-04 15:29:01 -05:00
|
|
|
if (G_VALUE_HOLDS_STRING (&v))
|
|
|
|
return g_value_get_string (&v);
|
|
|
|
return NULL;
|
2003-09-01 15:20:52 -05:00
|
|
|
}
|
|
|
|
|
2010-12-15 20:11:53 -06:00
|
|
|
gboolean
|
|
|
|
xaccTransGetIsClosingTxn (const Transaction *trans)
|
|
|
|
{
|
2015-05-08 15:33:40 -05:00
|
|
|
if (!trans) return FALSE;
|
2018-12-31 07:48:26 -06:00
|
|
|
if (trans->isClosingTxn_cached == -1)
|
|
|
|
{
|
|
|
|
Transaction* trans_nonconst = (Transaction*) trans;
|
|
|
|
GValue v = G_VALUE_INIT;
|
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, trans_is_closing_str);
|
|
|
|
if (G_VALUE_HOLDS_INT64 (&v))
|
|
|
|
trans_nonconst->isClosingTxn_cached = (g_value_get_int64 (&v) ? 1 : 0);
|
|
|
|
else
|
|
|
|
trans_nonconst->isClosingTxn_cached = 0;
|
2021-05-30 09:34:30 -05:00
|
|
|
g_value_unset (&v);
|
2018-12-31 07:48:26 -06:00
|
|
|
}
|
|
|
|
return (trans->isClosingTxn_cached == 1)
|
|
|
|
? TRUE
|
|
|
|
: FALSE;
|
2010-12-15 20:11:53 -06:00
|
|
|
}
|
|
|
|
|
2003-09-01 15:20:52 -05:00
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2012-12-01 16:44:53 -06:00
|
|
|
time64
|
2002-12-07 07:05:45 -06:00
|
|
|
xaccTransGetDate (const Transaction *trans)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2017-12-31 06:37:02 -06:00
|
|
|
return trans ? trans->date_posted : 0;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2013-02-28 03:52:12 -06:00
|
|
|
/*################## Added for Reg2 #################*/
|
|
|
|
time64
|
|
|
|
xaccTransGetDateEntered (const Transaction *trans)
|
|
|
|
{
|
2018-09-30 12:10:50 -05:00
|
|
|
return trans ? trans->date_entered : 0;
|
2013-02-28 03:52:12 -06:00
|
|
|
}
|
|
|
|
/*################## Added for Reg2 #################*/
|
|
|
|
|
2017-12-16 10:29:25 -06:00
|
|
|
time64
|
|
|
|
xaccTransRetDatePosted (const Transaction *trans)
|
|
|
|
{
|
2017-12-31 06:37:02 -06:00
|
|
|
return trans ? trans->date_posted : 0;
|
2017-12-16 10:29:25 -06:00
|
|
|
}
|
|
|
|
|
2010-03-17 14:23:40 -05:00
|
|
|
GDate
|
|
|
|
xaccTransGetDatePostedGDate (const Transaction *trans)
|
|
|
|
{
|
|
|
|
GDate result;
|
2016-07-03 10:56:52 -05:00
|
|
|
g_date_clear (&result, 1);
|
2010-03-17 14:23:40 -05:00
|
|
|
if (trans)
|
|
|
|
{
|
|
|
|
/* Can we look up this value in the kvp slot? If yes, use it
|
|
|
|
* from there because it doesn't suffer from time zone
|
|
|
|
* shifts. */
|
2017-11-02 14:42:22 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, TRANS_DATE_POSTED);
|
2015-06-04 15:29:01 -05:00
|
|
|
if (G_VALUE_HOLDS_BOXED (&v))
|
|
|
|
result = *(GDate*)g_value_get_boxed (&v);
|
2021-05-30 09:34:30 -05:00
|
|
|
g_value_unset (&v);
|
2018-11-11 02:07:34 -06:00
|
|
|
if (! g_date_valid (&result) || gdate_to_time64 (result) == INT64_MAX)
|
2017-12-12 13:50:24 -06:00
|
|
|
{
|
2018-11-11 02:07:34 -06:00
|
|
|
/* Well, this txn doesn't have a valid GDate saved in a slot.
|
|
|
|
* time64_to_gdate() uses local time and we want UTC so we have
|
|
|
|
* to write it out.
|
2017-12-12 13:50:24 -06:00
|
|
|
*/
|
|
|
|
time64 time = xaccTransGetDate(trans);
|
|
|
|
struct tm *stm = gnc_gmtime(&time);
|
2017-12-23 17:40:01 -06:00
|
|
|
if (stm)
|
|
|
|
{
|
|
|
|
g_date_set_dmy(&result, stm->tm_mday,
|
|
|
|
(GDateMonth)(stm->tm_mon + 1),
|
|
|
|
stm->tm_year + 1900);
|
|
|
|
free(stm);
|
|
|
|
}
|
2017-12-12 13:50:24 -06:00
|
|
|
}
|
2010-03-17 14:23:40 -05:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-12-16 10:29:25 -06:00
|
|
|
time64
|
|
|
|
xaccTransRetDateEntered (const Transaction *trans)
|
|
|
|
{
|
2017-12-31 06:37:02 -06:00
|
|
|
return trans ? trans->date_entered : 0;
|
2017-12-16 10:29:25 -06:00
|
|
|
}
|
|
|
|
|
2017-12-31 06:37:02 -06:00
|
|
|
time64
|
|
|
|
xaccTransRetDateDue(const Transaction *trans)
|
2001-11-26 22:47:19 -06:00
|
|
|
{
|
2017-12-31 06:37:02 -06:00
|
|
|
time64 ret = 0;
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2017-12-31 06:37:02 -06:00
|
|
|
if (!trans) return 0;
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, TRANS_DATE_DUE_KVP);
|
2015-06-04 15:29:01 -05:00
|
|
|
if (G_VALUE_HOLDS_BOXED (&v))
|
2018-09-14 03:47:31 -05:00
|
|
|
{
|
2018-08-02 20:19:15 -05:00
|
|
|
ret = ((Time64*)g_value_get_boxed (&v))->t;
|
2018-09-14 03:47:31 -05:00
|
|
|
g_value_unset (&v);
|
|
|
|
}
|
2017-12-31 06:37:02 -06:00
|
|
|
if (!ret)
|
|
|
|
return xaccTransRetDatePosted (trans);
|
|
|
|
return ret;
|
2002-02-03 14:01:08 -06:00
|
|
|
}
|
|
|
|
|
2001-11-29 22:25:17 -06:00
|
|
|
char
|
2002-12-07 07:05:45 -06:00
|
|
|
xaccTransGetTxnType (const Transaction *trans)
|
2001-11-29 22:25:17 -06:00
|
|
|
{
|
2015-06-04 15:29:01 -05:00
|
|
|
const char *s = NULL;
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2021-05-30 09:34:30 -05:00
|
|
|
char ret = TXN_TYPE_NONE;
|
2015-05-08 15:33:40 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!trans) return TXN_TYPE_NONE;
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, TRANS_TXN_TYPE_KVP);
|
2015-06-04 15:29:01 -05:00
|
|
|
if (G_VALUE_HOLDS_STRING (&v))
|
2021-05-30 09:34:30 -05:00
|
|
|
{
|
2015-06-04 15:29:01 -05:00
|
|
|
s = g_value_get_string (&v);
|
2021-05-30 09:34:30 -05:00
|
|
|
if (s && strlen (s) == 1)
|
|
|
|
ret = s[0];
|
|
|
|
}
|
|
|
|
g_value_unset (&v);
|
|
|
|
return ret;
|
2001-11-29 22:25:17 -06:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
const char *
|
2018-09-09 15:49:52 -05:00
|
|
|
xaccTransGetReadOnly (Transaction *trans)
|
2002-11-05 00:41:45 -06:00
|
|
|
{
|
2018-09-09 15:49:52 -05:00
|
|
|
if (!trans)
|
|
|
|
return NULL;
|
2015-05-08 15:33:40 -05:00
|
|
|
|
2018-09-09 15:49:52 -05:00
|
|
|
if (!trans->reason_cache_valid)
|
|
|
|
{
|
|
|
|
GValue v = G_VALUE_INIT;
|
|
|
|
qof_instance_get_kvp (QOF_INSTANCE(trans), &v, 1, TRANS_READ_ONLY_REASON);
|
|
|
|
|
|
|
|
/* Clear possible old cache value first */
|
2018-09-09 17:02:53 -05:00
|
|
|
g_free (trans->readonly_reason);
|
2018-09-09 15:49:52 -05:00
|
|
|
trans->readonly_reason = NULL;
|
|
|
|
|
|
|
|
/* Then set the new one */
|
|
|
|
if (G_VALUE_HOLDS_STRING (&v))
|
2018-09-09 17:02:53 -05:00
|
|
|
{
|
2018-09-09 15:49:52 -05:00
|
|
|
trans->readonly_reason = g_value_dup_string (&v);
|
2018-09-09 17:02:53 -05:00
|
|
|
g_value_unset (&v);
|
|
|
|
}
|
2018-09-10 03:24:49 -05:00
|
|
|
trans->reason_cache_valid = TRUE;
|
2018-09-09 15:49:52 -05:00
|
|
|
}
|
|
|
|
return trans->readonly_reason;
|
2002-11-05 00:41:45 -06:00
|
|
|
}
|
|
|
|
|
2014-12-23 11:01:18 -06:00
|
|
|
static gboolean
|
|
|
|
xaccTransIsSXTemplate (const Transaction * trans)
|
|
|
|
{
|
|
|
|
Split *split0 = xaccTransGetSplit (trans, 0);
|
|
|
|
if (split0 != NULL)
|
|
|
|
{
|
2014-12-23 20:37:45 -06:00
|
|
|
char* formula = NULL;
|
|
|
|
g_object_get (split0, "sx-debit-formula", &formula, NULL);
|
|
|
|
if (formula != NULL)
|
|
|
|
{
|
|
|
|
g_free (formula);
|
2014-12-23 11:01:18 -06:00
|
|
|
return TRUE;
|
2014-12-23 20:37:45 -06:00
|
|
|
}
|
|
|
|
g_object_get (split0, "sx-credit-formula", &formula, NULL);
|
|
|
|
if (formula != NULL)
|
|
|
|
{
|
|
|
|
g_free (formula);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2014-12-23 11:01:18 -06:00
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2012-03-24 17:34:44 -05:00
|
|
|
gboolean xaccTransIsReadonlyByPostedDate(const Transaction *trans)
|
|
|
|
{
|
|
|
|
GDate *threshold_date;
|
|
|
|
GDate trans_date;
|
|
|
|
const QofBook *book = xaccTransGetBook (trans);
|
|
|
|
gboolean result;
|
|
|
|
g_assert(trans);
|
|
|
|
|
2012-03-24 17:34:59 -05:00
|
|
|
if (!qof_book_uses_autoreadonly(book))
|
2012-03-24 17:34:44 -05:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2014-12-23 11:01:18 -06:00
|
|
|
if (xaccTransIsSXTemplate (trans))
|
|
|
|
return FALSE;
|
2014-12-22 16:19:52 -06:00
|
|
|
|
2012-03-24 17:34:59 -05:00
|
|
|
threshold_date = qof_book_get_autoreadonly_gdate(book);
|
2012-03-25 14:13:16 -05:00
|
|
|
g_assert(threshold_date); // ok because we checked uses_autoreadonly before
|
2012-03-24 17:34:44 -05:00
|
|
|
trans_date = xaccTransGetDatePostedGDate(trans);
|
|
|
|
|
|
|
|
// g_warning("there is auto-read-only with days=%d, trans_date_day=%d, threshold_date_day=%d",
|
|
|
|
// qof_book_get_num_days_autofreeze(book),
|
|
|
|
// g_date_get_day(&trans_date),
|
|
|
|
// g_date_get_day(threshold_date));
|
|
|
|
|
|
|
|
if (g_date_compare(&trans_date, threshold_date) < 0)
|
|
|
|
{
|
|
|
|
//g_warning("we are auto-read-only");
|
|
|
|
result = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = FALSE;
|
|
|
|
}
|
|
|
|
g_date_free(threshold_date);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-10-18 03:15:21 -05:00
|
|
|
/*################## Added for Reg2 #################*/
|
|
|
|
|
|
|
|
gboolean xaccTransInFutureByPostedDate (const Transaction *trans)
|
|
|
|
{
|
2013-05-02 09:41:56 -05:00
|
|
|
time64 present;
|
2012-10-18 03:15:21 -05:00
|
|
|
gboolean result;
|
|
|
|
g_assert(trans);
|
|
|
|
|
2013-05-02 09:41:56 -05:00
|
|
|
present = gnc_time64_get_today_end ();
|
2012-10-18 03:15:21 -05:00
|
|
|
|
2017-12-31 06:37:02 -06:00
|
|
|
if (trans->date_posted > present)
|
2012-10-18 03:15:21 -05:00
|
|
|
result = TRUE;
|
|
|
|
else
|
|
|
|
result = FALSE;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*################## Added for Reg2 #################*/
|
2012-03-24 17:34:44 -05:00
|
|
|
|
2002-10-25 22:54:14 -05:00
|
|
|
gboolean
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransHasReconciledSplitsByAccount (const Transaction *trans,
|
2003-09-01 15:20:52 -05:00
|
|
|
const Account *account)
|
2002-10-25 22:54:14 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *node;
|
2002-10-25 22:54:14 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
for (node = xaccTransGetSplitList (trans); node; node = node->next)
|
|
|
|
{
|
|
|
|
Split *split = node->data;
|
2002-10-25 22:54:14 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!xaccTransStillHasSplit(trans, split))
|
|
|
|
continue;
|
|
|
|
if (account && (xaccSplitGetAccount(split) != account))
|
|
|
|
continue;
|
2002-10-25 22:54:14 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
switch (xaccSplitGetReconcile (split))
|
|
|
|
{
|
|
|
|
case YREC:
|
|
|
|
case FREC:
|
|
|
|
return TRUE;
|
2002-10-25 22:54:14 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2002-10-25 22:54:14 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return FALSE;
|
2002-10-25 22:54:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2002-12-07 07:05:45 -06:00
|
|
|
xaccTransHasReconciledSplits (const Transaction *trans)
|
2002-10-25 22:54:14 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
return xaccTransHasReconciledSplitsByAccount (trans, NULL);
|
2002-10-25 22:54:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-06-15 22:48:59 -05:00
|
|
|
gboolean
|
|
|
|
xaccTransHasSplitsInStateByAccount (const Transaction *trans,
|
2003-09-01 15:20:52 -05:00
|
|
|
const char state,
|
|
|
|
const Account *account)
|
2003-06-15 22:48:59 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *node;
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
for (node = xaccTransGetSplitList (trans); node; node = node->next)
|
|
|
|
{
|
|
|
|
Split *split = node->data;
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!xaccTransStillHasSplit(trans, split))
|
|
|
|
continue;
|
|
|
|
if (account && (xaccSplitGetAccount(split) != account))
|
|
|
|
continue;
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (split->reconciled == state)
|
|
|
|
return TRUE;
|
|
|
|
}
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return FALSE;
|
2003-06-15 22:48:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
xaccTransHasSplitsInState (const Transaction *trans, const char state)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
return xaccTransHasSplitsInStateByAccount (trans, state, NULL);
|
2003-06-15 22:48:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
|
|
|
|
|
|
|
|
2003-06-09 23:30:54 -05:00
|
|
|
/* ====================================================================== */
|
|
|
|
|
2003-08-16 16:13:31 -05:00
|
|
|
static int
|
2003-06-09 23:30:54 -05:00
|
|
|
counter_thunk(Transaction *t, void *data)
|
|
|
|
{
|
|
|
|
(*((guint*)data))++;
|
2003-08-16 16:13:31 -05:00
|
|
|
return 0;
|
2003-06-09 23:30:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
guint
|
2003-06-24 19:52:46 -05:00
|
|
|
gnc_book_count_transactions(QofBook *book)
|
2003-06-09 23:30:54 -05:00
|
|
|
{
|
|
|
|
guint count = 0;
|
2007-02-22 19:23:31 -06:00
|
|
|
xaccAccountTreeForEachTransaction(gnc_book_get_root_account(book),
|
2010-03-02 15:40:28 -06:00
|
|
|
counter_thunk, (void*)&count);
|
2003-06-09 23:30:54 -05:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2001-10-01 00:42:23 -05:00
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
|
|
|
|
|
|
|
void
|
2006-01-01 16:26:15 -06:00
|
|
|
xaccTransVoid(Transaction *trans, const char *reason)
|
2001-10-01 00:42:23 -05:00
|
|
|
{
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2011-07-17 12:35:30 -05:00
|
|
|
char iso8601_str[ISO_DATELENGTH + 1] = "";
|
2001-10-08 20:47:55 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_return_if_fail(trans && reason);
|
2001-10-01 00:42:23 -05:00
|
|
|
|
2016-03-19 08:05:25 -05:00
|
|
|
/* Prevent voiding transactions that are already marked
|
|
|
|
* read only, for example generated by the business features.
|
|
|
|
*/
|
|
|
|
if (xaccTransGetReadOnly (trans))
|
|
|
|
{
|
|
|
|
PWARN ("Refusing to void a read-only transaction!");
|
|
|
|
return;
|
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransBeginEdit(trans);
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, trans_notes_str);
|
2015-06-04 15:29:01 -05:00
|
|
|
if (G_VALUE_HOLDS_STRING (&v))
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, void_former_notes_str);
|
2015-06-04 15:29:01 -05:00
|
|
|
else
|
|
|
|
g_value_init (&v, G_TYPE_STRING);
|
2001-10-01 00:42:23 -05:00
|
|
|
|
2015-05-08 15:33:40 -05:00
|
|
|
g_value_set_string (&v, _("Voided transaction"));
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, trans_notes_str);
|
2015-05-08 15:33:40 -05:00
|
|
|
g_value_set_string (&v, reason);
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, void_reason_str);
|
2001-10-01 00:42:23 -05:00
|
|
|
|
2018-08-02 20:19:15 -05:00
|
|
|
gnc_time64_to_iso8601_buff (gnc_time(NULL), iso8601_str);
|
2015-05-08 15:33:40 -05:00
|
|
|
g_value_set_string (&v, iso8601_str);
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, void_time_str);
|
2021-05-30 09:34:30 -05:00
|
|
|
g_value_unset (&v);
|
2001-10-08 20:47:55 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
FOR_EACH_SPLIT(trans, xaccSplitVoid(s));
|
2001-10-01 00:42:23 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Dirtying taken care of by SetReadOnly */
|
|
|
|
xaccTransSetReadOnly(trans, _("Transaction Voided"));
|
|
|
|
xaccTransCommitEdit(trans);
|
2001-10-01 00:42:23 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gboolean
|
2002-12-07 07:05:45 -06:00
|
|
|
xaccTransGetVoidStatus(const Transaction *trans)
|
2001-10-01 00:42:23 -05:00
|
|
|
{
|
2015-06-04 15:29:01 -05:00
|
|
|
const char *s = NULL;
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2021-05-30 09:34:30 -05:00
|
|
|
gboolean retval = FALSE;
|
2010-03-02 15:40:28 -06:00
|
|
|
g_return_val_if_fail(trans, FALSE);
|
2015-05-08 15:33:40 -05:00
|
|
|
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, void_reason_str);
|
2015-06-04 15:29:01 -05:00
|
|
|
if (G_VALUE_HOLDS_STRING (&v))
|
2021-05-30 09:34:30 -05:00
|
|
|
{
|
2015-06-04 15:29:01 -05:00
|
|
|
s = g_value_get_string (&v);
|
2021-05-30 09:34:30 -05:00
|
|
|
retval = (s && (s[0] != '\0'));
|
|
|
|
}
|
|
|
|
g_value_unset (&v);
|
|
|
|
return retval;
|
2001-10-01 00:42:23 -05:00
|
|
|
}
|
|
|
|
|
2006-04-15 11:40:03 -05:00
|
|
|
const char *
|
2002-12-07 07:05:45 -06:00
|
|
|
xaccTransGetVoidReason(const Transaction *trans)
|
2001-10-01 00:42:23 -05:00
|
|
|
{
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
|
|
|
g_return_val_if_fail(trans, FALSE);
|
|
|
|
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, void_reason_str);
|
2015-06-04 15:29:01 -05:00
|
|
|
if (G_VALUE_HOLDS_STRING (&v))
|
|
|
|
return g_value_get_string (&v);
|
|
|
|
return NULL;
|
2001-10-01 00:42:23 -05:00
|
|
|
}
|
|
|
|
|
2017-12-23 12:06:59 -06:00
|
|
|
time64
|
2002-12-07 07:05:45 -06:00
|
|
|
xaccTransGetVoidTime(const Transaction *tr)
|
2001-10-08 20:47:55 -05:00
|
|
|
{
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2015-06-04 15:29:01 -05:00
|
|
|
const char *s = NULL;
|
2017-12-23 12:06:59 -06:00
|
|
|
time64 void_time = 0;
|
2001-12-06 03:30:25 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_return_val_if_fail(tr, void_time);
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (tr), &v, 1, void_time_str);
|
2015-06-04 15:29:01 -05:00
|
|
|
if (G_VALUE_HOLDS_STRING (&v))
|
2021-05-30 09:34:30 -05:00
|
|
|
{
|
2015-06-04 15:29:01 -05:00
|
|
|
s = g_value_get_string (&v);
|
2021-05-30 09:34:30 -05:00
|
|
|
if (s)
|
|
|
|
void_time = gnc_iso8601_to_time64_gmt (s);
|
|
|
|
}
|
|
|
|
g_value_unset (&v);
|
2015-05-08 15:33:40 -05:00
|
|
|
return void_time;
|
2001-10-08 20:47:55 -05:00
|
|
|
}
|
* src/engine/GNCId.c: Implement xaccForeachEntity() as a which
allows a traversal of all entities of a particular type.
* Register GncObject_t descriptions for Splits, Transactions, and
Accounts. Move the QueryObject definitions into the actual module
sources for Transactions, Splits, Accounts, and Books. This
allows QueryNew searches for Splits, Transactions, and Accounts.
* gnc-engine.c: call the registration functions for Splits,
Transactions, Accounts, and Books to enable searching using the
new search subsystem.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@6913 57a11ea4-9604-0410-9ed3-97b8803252fd
2002-05-24 21:50:24 -05:00
|
|
|
|
2003-06-15 22:48:59 -05:00
|
|
|
void
|
2006-01-01 16:26:15 -06:00
|
|
|
xaccTransUnvoid (Transaction *trans)
|
2003-06-15 22:48:59 -05:00
|
|
|
{
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2015-06-04 15:29:01 -05:00
|
|
|
const char *s = NULL;
|
2010-03-02 15:40:28 -06:00
|
|
|
g_return_if_fail(trans);
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, void_reason_str);
|
2015-06-04 15:29:01 -05:00
|
|
|
if (G_VALUE_HOLDS_STRING (&v))
|
|
|
|
s = g_value_get_string (&v);
|
2021-05-30 09:34:30 -05:00
|
|
|
g_value_unset (&v);
|
2015-05-08 15:33:40 -05:00
|
|
|
if (s == NULL) return; /* Transaction isn't voided. Bail. */
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransBeginEdit(trans);
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, void_former_notes_str);
|
2015-06-04 15:29:01 -05:00
|
|
|
if (G_VALUE_HOLDS_STRING (&v))
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, trans_notes_str);
|
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), NULL, 1, void_former_notes_str);
|
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), NULL, 1, void_reason_str);
|
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (trans), NULL, 1, void_time_str);
|
2021-05-30 09:34:30 -05:00
|
|
|
g_value_unset (&v);
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
FOR_EACH_SPLIT(trans, xaccSplitUnvoid(s));
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Dirtying taken care of by ClearReadOnly */
|
|
|
|
xaccTransClearReadOnly(trans);
|
|
|
|
xaccTransCommitEdit(trans);
|
2003-06-15 22:48:59 -05:00
|
|
|
}
|
|
|
|
|
2006-05-03 19:06:58 -05:00
|
|
|
Transaction *
|
|
|
|
xaccTransReverse (Transaction *orig)
|
2003-06-15 22:48:59 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
Transaction *trans;
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2010-03-02 15:40:28 -06:00
|
|
|
g_return_val_if_fail(orig, NULL);
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2021-06-12 15:23:36 -05:00
|
|
|
/* First edit, dirty, and commit orig to ensure that any trading
|
|
|
|
* splits are correctly balanced.
|
|
|
|
*/
|
|
|
|
xaccTransBeginEdit (orig);
|
|
|
|
qof_instance_set_dirty (QOF_INSTANCE (orig));
|
|
|
|
xaccTransCommitEdit (orig);
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
trans = xaccTransClone(orig);
|
2021-06-12 15:23:36 -05:00
|
|
|
g_return_val_if_fail (trans, NULL);
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransBeginEdit(trans);
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Reverse the values on each split. Clear per-split info. */
|
|
|
|
FOR_EACH_SPLIT(trans,
|
|
|
|
{
|
|
|
|
xaccSplitSetAmount(s, gnc_numeric_neg(xaccSplitGetAmount(s)));
|
|
|
|
xaccSplitSetValue(s, gnc_numeric_neg(xaccSplitGetValue(s)));
|
|
|
|
xaccSplitSetReconcile(s, NREC);
|
|
|
|
});
|
2003-06-15 22:48:59 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Now update the original with a pointer to the new one */
|
2015-05-08 15:33:40 -05:00
|
|
|
g_value_init (&v, GNC_TYPE_GUID);
|
|
|
|
g_value_set_boxed (&v, xaccTransGetGUID(trans));
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (orig), &v, 1, TRANS_REVERSED_BY);
|
2021-05-30 09:34:30 -05:00
|
|
|
g_value_unset (&v);
|
2006-05-03 19:06:58 -05:00
|
|
|
|
2016-03-19 08:32:14 -05:00
|
|
|
/* Make sure the reverse transaction is not read-only */
|
|
|
|
xaccTransClearReadOnly(trans);
|
|
|
|
|
2013-11-30 19:30:03 -06:00
|
|
|
qof_instance_set_dirty(QOF_INSTANCE(trans));
|
2010-03-02 15:40:28 -06:00
|
|
|
xaccTransCommitEdit(trans);
|
|
|
|
return trans;
|
2006-05-03 19:06:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
Transaction *
|
|
|
|
xaccTransGetReversedBy(const Transaction *trans)
|
|
|
|
{
|
2015-05-08 15:33:40 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2021-05-30 09:34:30 -05:00
|
|
|
Transaction *retval = NULL;
|
2006-05-03 19:06:58 -05:00
|
|
|
g_return_val_if_fail(trans, NULL);
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE(trans), &v, 1, TRANS_REVERSED_BY);
|
2015-06-04 15:29:01 -05:00
|
|
|
if (G_VALUE_HOLDS_BOXED (&v))
|
2021-05-30 09:34:30 -05:00
|
|
|
{
|
|
|
|
GncGUID* guid = g_value_get_boxed (&v);
|
|
|
|
retval = xaccTransLookup(guid, qof_instance_get_book (trans));
|
|
|
|
}
|
|
|
|
g_value_unset (&v);
|
|
|
|
return retval;
|
2003-06-15 22:48:59 -05:00
|
|
|
}
|
|
|
|
|
2006-03-03 18:10:12 -06:00
|
|
|
void
|
|
|
|
xaccTransScrubSplits (Transaction *trans)
|
|
|
|
{
|
|
|
|
gnc_commodity *currency;
|
|
|
|
|
|
|
|
if (!trans) return;
|
|
|
|
|
2006-05-04 19:40:15 -05:00
|
|
|
xaccTransBeginEdit(trans);
|
2006-03-03 18:10:12 -06:00
|
|
|
/* The split scrub expects the transaction to have a currency! */
|
|
|
|
currency = xaccTransGetCurrency (trans);
|
|
|
|
if (!currency)
|
|
|
|
PERR ("Transaction doesn't have a currency!");
|
|
|
|
|
|
|
|
FOR_EACH_SPLIT(trans, xaccSplitScrub(s));
|
2006-05-04 19:40:15 -05:00
|
|
|
xaccTransCommitEdit(trans);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ============================================================== */
|
|
|
|
/** The xaccTransScrubGainsDate() routine is used to keep the posted date
|
|
|
|
* of gains splits in sync with the posted date of the transaction
|
|
|
|
* that caused the gains.
|
2010-03-02 15:40:28 -06:00
|
|
|
*
|
2006-05-04 19:40:15 -05:00
|
|
|
* The posted date is kept in sync using a lazy-evaluation scheme.
|
|
|
|
* If xaccTransactionSetDatePosted() is called, the date change is
|
|
|
|
* accepted, and the split is marked date-dirty. If the posted date
|
|
|
|
* is queried for (using GetDatePosted()), then the transaction is
|
2010-03-02 15:40:28 -06:00
|
|
|
* evaluated. If it's a gains-transaction, then its date is copied
|
2006-05-04 19:40:15 -05:00
|
|
|
* from the source transaction that created the gains.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
xaccTransScrubGainsDate (Transaction *trans)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
SplitList *node;
|
|
|
|
for (node = trans->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
Split *s = node->data;
|
2006-05-04 19:40:15 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!xaccTransStillHasSplit(trans, s)) continue;
|
|
|
|
xaccSplitDetermineGainStatus(s);
|
2006-05-04 19:40:15 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if ((GAINS_STATUS_GAINS & s->gains) &&
|
2015-06-04 15:29:01 -05:00
|
|
|
s->gains_split &&
|
|
|
|
((s->gains_split->gains & GAINS_STATUS_DATE_DIRTY) ||
|
|
|
|
(s->gains & GAINS_STATUS_DATE_DIRTY)))
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
Transaction *source_trans = s->gains_split->parent;
|
|
|
|
s->gains &= ~GAINS_STATUS_DATE_DIRTY;
|
|
|
|
s->gains_split->gains &= ~GAINS_STATUS_DATE_DIRTY;
|
2017-12-31 06:37:02 -06:00
|
|
|
xaccTransSetDatePostedSecs(trans, source_trans->date_posted);
|
2010-03-02 15:40:28 -06:00
|
|
|
FOR_EACH_SPLIT(trans, s->gains &= ~GAINS_STATUS_DATE_DIRTY);
|
|
|
|
}
|
|
|
|
}
|
2006-05-04 19:40:15 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ============================================================== */
|
|
|
|
|
|
|
|
void
|
|
|
|
xaccTransScrubGains (Transaction *trans, Account *gain_acc)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
SplitList *node;
|
2006-05-04 19:40:15 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER("(trans=%p)", trans);
|
|
|
|
/* Lock down posted date, its to be synced to the posted date
|
|
|
|
* for the source of the cap gains. */
|
|
|
|
xaccTransScrubGainsDate(trans);
|
2006-05-04 19:40:15 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Fix up the split amount */
|
2006-05-04 19:40:15 -05:00
|
|
|
restart:
|
2010-03-02 15:40:28 -06:00
|
|
|
for (node = trans->splits; node; node = node->next)
|
|
|
|
{
|
|
|
|
Split *s = node->data;
|
|
|
|
|
|
|
|
if (!xaccTransStillHasSplit(trans, s)) continue;
|
|
|
|
|
|
|
|
xaccSplitDetermineGainStatus(s);
|
|
|
|
if (s->gains & GAINS_STATUS_ADIRTY)
|
|
|
|
{
|
|
|
|
gboolean altered = FALSE;
|
|
|
|
s->gains &= ~GAINS_STATUS_ADIRTY;
|
|
|
|
if (s->lot)
|
|
|
|
altered = xaccScrubLot(s->lot);
|
|
|
|
else
|
|
|
|
altered = xaccSplitAssign(s);
|
|
|
|
if (altered) goto restart;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fix up gains split value */
|
|
|
|
FOR_EACH_SPLIT(trans,
|
|
|
|
if ((s->gains & GAINS_STATUS_VDIRTY) ||
|
|
|
|
(s->gains_split &&
|
|
|
|
(s->gains_split->gains & GAINS_STATUS_VDIRTY)))
|
2015-06-04 15:29:01 -05:00
|
|
|
xaccSplitComputeCapGains(s, gain_acc);
|
|
|
|
);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
LEAVE("(trans=%p)", trans);
|
2006-03-03 18:10:12 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
Split *
|
2006-05-04 19:40:15 -05:00
|
|
|
xaccTransFindSplitByAccount(const Transaction *trans, const Account *acc)
|
2006-03-03 18:10:12 -06:00
|
|
|
{
|
|
|
|
if (!trans || !acc) return NULL;
|
|
|
|
FOR_EACH_SPLIT(trans, if (xaccSplitGetAccount(s) == acc) return s);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-02-21 15:03:39 -06:00
|
|
|
static void
|
|
|
|
record_price (Split *split,
|
|
|
|
PriceSource source)
|
|
|
|
{
|
|
|
|
Transaction *trans;
|
|
|
|
Account *account;
|
|
|
|
QofBook* book;
|
|
|
|
GNCPriceDB* pricedb;
|
|
|
|
gnc_commodity* comm;
|
|
|
|
gnc_commodity* curr;
|
|
|
|
GNCPrice* price;
|
|
|
|
gnc_numeric price_value, value, amount;
|
|
|
|
int scu;
|
|
|
|
time64 time;
|
|
|
|
gboolean swap;
|
|
|
|
|
|
|
|
account = xaccSplitGetAccount (split);
|
|
|
|
if (!xaccAccountIsPriced (account))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
amount = xaccSplitGetAmount (split);
|
|
|
|
if (gnc_numeric_zero_p (amount))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
trans = xaccSplitGetParent (split);
|
|
|
|
value = gnc_numeric_div (xaccSplitGetValue (split), amount,
|
|
|
|
GNC_DENOM_AUTO,
|
|
|
|
GNC_HOW_DENOM_EXACT);
|
|
|
|
book = qof_instance_get_book (QOF_INSTANCE (account));
|
|
|
|
pricedb = gnc_pricedb_get_db (book);
|
|
|
|
comm = xaccAccountGetCommodity (account);
|
|
|
|
curr = xaccTransGetCurrency (trans);
|
|
|
|
scu = gnc_commodity_get_fraction (curr);
|
|
|
|
swap = FALSE;
|
|
|
|
time = xaccTransGetDate (trans);
|
|
|
|
price = gnc_pricedb_lookup_day_t64 (pricedb, comm, curr, time);
|
|
|
|
if (gnc_commodity_equiv (comm, gnc_price_get_currency (price)))
|
|
|
|
swap = TRUE;
|
|
|
|
|
|
|
|
if (price)
|
|
|
|
{
|
2021-06-10 13:27:58 -05:00
|
|
|
PriceSource oldsource = gnc_price_get_source (price);
|
2021-02-21 15:03:39 -06:00
|
|
|
price_value = gnc_price_get_value (price);
|
|
|
|
if (gnc_numeric_equal (swap ? gnc_numeric_invert (value) : value,
|
|
|
|
price_value))
|
|
|
|
{
|
|
|
|
gnc_price_unref (price);
|
|
|
|
return;
|
|
|
|
}
|
2021-06-10 13:27:58 -05:00
|
|
|
if (oldsource < source &&
|
|
|
|
!(oldsource == PRICE_SOURCE_XFER_DLG_VAL &&
|
|
|
|
source == PRICE_SOURCE_SPLIT_REG))
|
2021-02-21 15:03:39 -06:00
|
|
|
{
|
|
|
|
/* Existing price is preferred over this one. */
|
|
|
|
gnc_price_unref (price);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (swap)
|
|
|
|
{
|
|
|
|
value = gnc_numeric_invert (value);
|
|
|
|
scu = gnc_commodity_get_fraction (comm);
|
|
|
|
}
|
|
|
|
value = gnc_numeric_convert (value, scu * COMMODITY_DENOM_MULT,
|
|
|
|
GNC_HOW_RND_ROUND_HALF_UP);
|
|
|
|
gnc_price_begin_edit (price);
|
|
|
|
gnc_price_set_time64 (price, time);
|
|
|
|
gnc_price_set_source (price, source);
|
|
|
|
gnc_price_set_typestr (price, PRICE_TYPE_TRN);
|
|
|
|
gnc_price_set_value (price, value);
|
|
|
|
gnc_price_commit_edit (price);
|
|
|
|
gnc_price_unref (price);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
value = gnc_numeric_convert (value, scu * COMMODITY_DENOM_MULT,
|
|
|
|
GNC_HOW_RND_ROUND_HALF_UP);
|
|
|
|
price = gnc_price_create (book);
|
|
|
|
gnc_price_begin_edit (price);
|
|
|
|
gnc_price_set_commodity (price, comm);
|
|
|
|
gnc_price_set_currency (price, curr);
|
|
|
|
gnc_price_set_time64 (price, time);
|
|
|
|
gnc_price_set_source (price, source);
|
|
|
|
gnc_price_set_typestr (price, PRICE_TYPE_TRN);
|
|
|
|
gnc_price_set_value (price, value);
|
|
|
|
gnc_pricedb_add_price (pricedb, price);
|
|
|
|
gnc_price_commit_edit (price);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xaccTransRecordPrice (Transaction *trans, PriceSource source)
|
|
|
|
{
|
|
|
|
/* XXX: This should have been part of xaccSplitCommitEdit. */
|
|
|
|
for (GList *n = xaccTransGetSplitList (trans); n; n = n->next)
|
|
|
|
record_price (n->data, source);
|
|
|
|
}
|
2014-05-07 08:37:14 -05:00
|
|
|
|
2003-06-10 20:23:18 -05:00
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
2003-10-19 00:11:07 -05:00
|
|
|
/* QofObject function implementation */
|
* src/engine/GNCId.c: Implement xaccForeachEntity() as a which
allows a traversal of all entities of a particular type.
* Register GncObject_t descriptions for Splits, Transactions, and
Accounts. Move the QueryObject definitions into the actual module
sources for Transactions, Splits, Accounts, and Books. This
allows QueryNew searches for Splits, Transactions, and Accounts.
* gnc-engine.c: call the registration functions for Splits,
Transactions, Accounts, and Books to enable searching using the
new search subsystem.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@6913 57a11ea4-9604-0410-9ed3-97b8803252fd
2002-05-24 21:50:24 -05:00
|
|
|
|
2011-01-09 12:01:47 -06:00
|
|
|
static void
|
|
|
|
destroy_tx_on_book_close(QofInstance *ent, gpointer data)
|
|
|
|
{
|
|
|
|
Transaction* tx = GNC_TRANSACTION(ent);
|
|
|
|
|
|
|
|
xaccTransDestroy(tx);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Handles book end - frees all transactions from the book
|
|
|
|
*
|
|
|
|
* @param book Book being closed
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
gnc_transaction_book_end(QofBook* book)
|
|
|
|
{
|
|
|
|
QofCollection *col;
|
|
|
|
|
|
|
|
col = qof_book_get_collection(book, GNC_ID_TRANS);
|
|
|
|
qof_collection_foreach(col, destroy_tx_on_book_close, NULL);
|
|
|
|
}
|
|
|
|
|
2010-02-27 12:41:49 -06:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
/* MSVC compiler doesn't have C99 "designated initializers"
|
|
|
|
* so we wrap them in a macro that is empty on MSVC. */
|
|
|
|
# define DI(x) /* */
|
|
|
|
#else
|
|
|
|
# define DI(x) x
|
|
|
|
#endif
|
|
|
|
|
2003-10-19 00:11:07 -05:00
|
|
|
/* Hook into the QofObject registry */
|
2010-03-02 15:40:28 -06:00
|
|
|
static QofObject trans_object_def =
|
|
|
|
{
|
|
|
|
DI(.interface_version = ) QOF_OBJECT_VERSION,
|
|
|
|
DI(.e_type = ) GNC_ID_TRANS,
|
|
|
|
DI(.type_label = ) "Transaction",
|
|
|
|
DI(.create = ) (gpointer)xaccMallocTransaction,
|
|
|
|
DI(.book_begin = ) NULL,
|
2011-01-09 12:01:47 -06:00
|
|
|
DI(.book_end = ) gnc_transaction_book_end,
|
2010-03-02 15:40:28 -06:00
|
|
|
DI(.is_dirty = ) qof_collection_is_dirty,
|
|
|
|
DI(.mark_clean = ) qof_collection_mark_clean,
|
|
|
|
DI(.foreach = ) qof_collection_foreach,
|
|
|
|
DI(.printable = ) (const char * (*)(gpointer)) xaccTransGetDescription,
|
|
|
|
DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
|
* src/engine/GNCId.c: Implement xaccForeachEntity() as a which
allows a traversal of all entities of a particular type.
* Register GncObject_t descriptions for Splits, Transactions, and
Accounts. Move the QueryObject definitions into the actual module
sources for Transactions, Splits, Accounts, and Books. This
allows QueryNew searches for Splits, Transactions, and Accounts.
* gnc-engine.c: call the registration functions for Splits,
Transactions, Accounts, and Books to enable searching using the
new search subsystem.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@6913 57a11ea4-9604-0410-9ed3-97b8803252fd
2002-05-24 21:50:24 -05:00
|
|
|
};
|
|
|
|
|
2002-06-05 16:59:35 -05:00
|
|
|
static gboolean
|
2006-01-01 16:26:15 -06:00
|
|
|
trans_is_balanced_p (const Transaction *trans)
|
2002-06-05 16:59:35 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
return trans ? xaccTransIsBalanced(trans) : FALSE;
|
2002-06-05 16:59:35 -05:00
|
|
|
}
|
|
|
|
|
* src/engine/GNCId.c: Implement xaccForeachEntity() as a which
allows a traversal of all entities of a particular type.
* Register GncObject_t descriptions for Splits, Transactions, and
Accounts. Move the QueryObject definitions into the actual module
sources for Transactions, Splits, Accounts, and Books. This
allows QueryNew searches for Splits, Transactions, and Accounts.
* gnc-engine.c: call the registration functions for Splits,
Transactions, Accounts, and Books to enable searching using the
new search subsystem.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@6913 57a11ea4-9604-0410-9ed3-97b8803252fd
2002-05-24 21:50:24 -05:00
|
|
|
gboolean xaccTransRegister (void)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
static QofParam params[] =
|
2013-11-15 16:02:34 -06:00
|
|
|
{
|
2015-06-04 15:29:01 -05:00
|
|
|
{
|
|
|
|
TRANS_NUM, QOF_TYPE_STRING,
|
|
|
|
(QofAccessFunc)xaccTransGetNum,
|
|
|
|
(QofSetterFunc)qofTransSetNum,
|
|
|
|
qof_string_number_compare_func
|
|
|
|
},
|
|
|
|
{
|
|
|
|
TRANS_DESCRIPTION, QOF_TYPE_STRING,
|
|
|
|
(QofAccessFunc)xaccTransGetDescription,
|
|
|
|
(QofSetterFunc)qofTransSetDescription
|
|
|
|
},
|
|
|
|
{
|
|
|
|
TRANS_DATE_ENTERED, QOF_TYPE_DATE,
|
2018-04-26 08:48:06 -05:00
|
|
|
(QofAccessFunc)xaccTransRetDateEntered,
|
|
|
|
(QofSetterFunc)xaccTransSetDateEnteredSecs
|
2015-06-04 15:29:01 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
TRANS_DATE_POSTED, QOF_TYPE_DATE,
|
2018-04-26 08:48:06 -05:00
|
|
|
(QofAccessFunc)xaccTransRetDatePosted,
|
|
|
|
(QofSetterFunc)xaccTransSetDatePostedSecs
|
2015-06-04 15:29:01 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
TRANS_DATE_DUE, QOF_TYPE_DATE,
|
2018-04-26 08:48:06 -05:00
|
|
|
(QofAccessFunc)xaccTransRetDateDue, NULL
|
2015-06-04 15:29:01 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
TRANS_IMBALANCE, QOF_TYPE_NUMERIC,
|
|
|
|
(QofAccessFunc)xaccTransGetImbalanceValue, NULL
|
|
|
|
},
|
|
|
|
{
|
|
|
|
TRANS_NOTES, QOF_TYPE_STRING,
|
|
|
|
(QofAccessFunc)xaccTransGetNotes,
|
|
|
|
(QofSetterFunc)qofTransSetNotes
|
|
|
|
},
|
|
|
|
{
|
2020-08-15 19:05:21 -05:00
|
|
|
TRANS_DOCLINK, QOF_TYPE_STRING,
|
|
|
|
(QofAccessFunc)xaccTransGetDocLink,
|
|
|
|
(QofSetterFunc)xaccTransSetDocLink
|
2015-06-04 15:29:01 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
TRANS_IS_CLOSING, QOF_TYPE_BOOLEAN,
|
|
|
|
(QofAccessFunc)xaccTransGetIsClosingTxn, NULL
|
|
|
|
},
|
|
|
|
{
|
|
|
|
TRANS_IS_BALANCED, QOF_TYPE_BOOLEAN,
|
|
|
|
(QofAccessFunc)trans_is_balanced_p, NULL
|
|
|
|
},
|
|
|
|
{
|
|
|
|
TRANS_TYPE, QOF_TYPE_CHAR,
|
|
|
|
(QofAccessFunc)xaccTransGetTxnType,
|
|
|
|
(QofSetterFunc)xaccTransSetTxnType
|
|
|
|
},
|
|
|
|
{
|
|
|
|
TRANS_VOID_STATUS, QOF_TYPE_BOOLEAN,
|
|
|
|
(QofAccessFunc)xaccTransGetVoidStatus, NULL
|
|
|
|
},
|
|
|
|
{
|
|
|
|
TRANS_VOID_REASON, QOF_TYPE_STRING,
|
|
|
|
(QofAccessFunc)xaccTransGetVoidReason, NULL
|
|
|
|
},
|
|
|
|
{
|
|
|
|
TRANS_VOID_TIME, QOF_TYPE_DATE,
|
|
|
|
(QofAccessFunc)xaccTransGetVoidTime, NULL
|
|
|
|
},
|
|
|
|
{
|
|
|
|
TRANS_SPLITLIST, GNC_ID_SPLIT,
|
|
|
|
(QofAccessFunc)xaccTransGetSplitList, NULL
|
|
|
|
},
|
|
|
|
{
|
|
|
|
QOF_PARAM_BOOK, QOF_ID_BOOK,
|
|
|
|
(QofAccessFunc)qof_instance_get_book, NULL
|
|
|
|
},
|
|
|
|
{
|
|
|
|
QOF_PARAM_GUID, QOF_TYPE_GUID,
|
|
|
|
(QofAccessFunc)qof_entity_get_guid, NULL
|
|
|
|
},
|
|
|
|
{ NULL },
|
|
|
|
};
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
qof_class_register (GNC_ID_TRANS, (QofSortFunc)xaccTransOrder, params);
|
|
|
|
|
|
|
|
return qof_object_register (&trans_object_def);
|
* src/engine/GNCId.c: Implement xaccForeachEntity() as a which
allows a traversal of all entities of a particular type.
* Register GncObject_t descriptions for Splits, Transactions, and
Accounts. Move the QueryObject definitions into the actual module
sources for Transactions, Splits, Accounts, and Books. This
allows QueryNew searches for Splits, Transactions, and Accounts.
* gnc-engine.c: call the registration functions for Splits,
Transactions, Accounts, and Books to enable searching using the
new search subsystem.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@6913 57a11ea4-9604-0410-9ed3-97b8803252fd
2002-05-24 21:50:24 -05:00
|
|
|
}
|
|
|
|
|
2013-08-16 11:44:28 -05:00
|
|
|
TransTestFunctions*
|
|
|
|
_utest_trans_fill_functions (void)
|
|
|
|
{
|
|
|
|
TransTestFunctions *func = g_new (TransTestFunctions, 1);
|
|
|
|
|
|
|
|
func->mark_trans = mark_trans;
|
|
|
|
func->gen_event_trans = gen_event_trans;
|
|
|
|
func->xaccFreeTransaction = xaccFreeTransaction;
|
|
|
|
func->destroy_gains = destroy_gains;
|
|
|
|
func->do_destroy = do_destroy;
|
|
|
|
func->was_trans_emptied = was_trans_emptied;
|
|
|
|
func->trans_on_error = trans_on_error;
|
|
|
|
func->trans_cleanup_commit = trans_cleanup_commit;
|
|
|
|
func->xaccTransScrubGainsDate = xaccTransScrubGainsDate;
|
2014-05-07 08:37:14 -05:00
|
|
|
func->dupe_trans = dupe_trans;
|
2013-08-16 11:44:28 -05:00
|
|
|
return func;
|
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/************************ END OF ************************************\
|
|
|
|
\************************* FILE *************************************/
|