mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Restructure the src directory
It is split into - /libgnucash (for the non-gui bits) - /gnucash (for the gui) - /common (misc source files used by both) - /bindings (currently only holds python bindings) This is the first step in restructuring the code. It will need much more fine tuning later on.
This commit is contained in:
710
libgnucash/engine/Query.c
Normal file
710
libgnucash/engine/Query.c
Normal file
@@ -0,0 +1,710 @@
|
||||
/********************************************************************\
|
||||
* Query.c : api for finding transactions *
|
||||
* Copyright (C) 2000 Bill Gribble <grib@billgribble.com> *
|
||||
* Copyright (C) 2002 Linas Vepstas <linas@linas.org> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02110-1301, USA gnu@gnu.org *
|
||||
\********************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <platform.h>
|
||||
#if PLATFORM(WINDOWS)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <glib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <regex.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "gnc-lot.h"
|
||||
#include "Account.h"
|
||||
#include "Query.h"
|
||||
#include "Transaction.h"
|
||||
#include "TransactionP.h"
|
||||
|
||||
static QofLogModule log_module = GNC_MOD_QUERY;
|
||||
|
||||
static GSList *
|
||||
build_param_list_internal (const char *first, va_list rest)
|
||||
{
|
||||
GSList *list = NULL;
|
||||
char const *param;
|
||||
|
||||
for (param = first; param; param = va_arg (rest, const char *))
|
||||
list = g_slist_prepend (list, (gpointer)param);
|
||||
|
||||
return (g_slist_reverse (list));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* xaccQueryGetSplitsUniqueTrans
|
||||
* Get splits but no more than one from a given transaction.
|
||||
********************************************************************/
|
||||
|
||||
SplitList *
|
||||
xaccQueryGetSplitsUniqueTrans(QofQuery *q)
|
||||
{
|
||||
GList * splits = qof_query_run(q);
|
||||
GList * current;
|
||||
GList * result = NULL;
|
||||
GHashTable * trans_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
|
||||
for (current = splits; current; current = current->next)
|
||||
{
|
||||
Split *split = current->data;
|
||||
Transaction *trans = xaccSplitGetParent (split);
|
||||
|
||||
if (!g_hash_table_lookup (trans_hash, trans))
|
||||
{
|
||||
g_hash_table_insert (trans_hash, trans, trans);
|
||||
result = g_list_prepend (result, split);
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_destroy (trans_hash);
|
||||
|
||||
return g_list_reverse (result);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* xaccQueryGetTransactions
|
||||
* Get transactions matching the query terms, specifying whether
|
||||
* we require some or all splits to match
|
||||
********************************************************************/
|
||||
|
||||
static void
|
||||
query_match_all_filter_func(gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
Transaction * t = key;
|
||||
int num_matches = GPOINTER_TO_INT(value);
|
||||
GList ** matches = user_data;
|
||||
|
||||
if (num_matches == xaccTransCountSplits(t))
|
||||
{
|
||||
*matches = g_list_prepend(*matches, t);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
query_match_any_filter_func(gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
Transaction * t = key;
|
||||
GList ** matches = user_data;
|
||||
*matches = g_list_prepend(*matches, t);
|
||||
}
|
||||
|
||||
TransList *
|
||||
xaccQueryGetTransactions (QofQuery * q, query_txn_match_t runtype)
|
||||
{
|
||||
GList * splits = qof_query_run(q);
|
||||
GList * current = NULL;
|
||||
GList * retval = NULL;
|
||||
GHashTable * trans_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
Transaction * trans = NULL;
|
||||
gpointer val = NULL;
|
||||
int count = 0;
|
||||
|
||||
/* iterate over matching splits, incrementing a match-count in
|
||||
* the hash table */
|
||||
for (current = splits; current; current = current->next)
|
||||
{
|
||||
trans = xaccSplitGetParent((Split *)(current->data));
|
||||
|
||||
/* don't waste time looking up unless we need the count
|
||||
* information */
|
||||
if (runtype == QUERY_TXN_MATCH_ALL)
|
||||
{
|
||||
val = g_hash_table_lookup(trans_hash, trans);
|
||||
count = GPOINTER_TO_INT(val);
|
||||
}
|
||||
g_hash_table_insert(trans_hash, trans, GINT_TO_POINTER(count + 1));
|
||||
}
|
||||
|
||||
/* now pick out the transactions that match */
|
||||
if (runtype == QUERY_TXN_MATCH_ALL)
|
||||
{
|
||||
g_hash_table_foreach(trans_hash, query_match_all_filter_func,
|
||||
&retval);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_hash_table_foreach(trans_hash, query_match_any_filter_func,
|
||||
&retval);
|
||||
}
|
||||
|
||||
g_hash_table_destroy(trans_hash);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* xaccQueryGetLots
|
||||
* Get lots matching the query terms, specifying whether
|
||||
* we require some or all splits to match
|
||||
********************************************************************/
|
||||
|
||||
static void
|
||||
query_match_all_lot_filter_func(gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
GNCLot * l = key;
|
||||
int num_matches = GPOINTER_TO_INT(value);
|
||||
GList ** matches = user_data;
|
||||
|
||||
if (num_matches == gnc_lot_count_splits(l))
|
||||
{
|
||||
*matches = g_list_prepend(*matches, l);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
query_match_any_lot_filter_func(gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
GNCLot * t = key;
|
||||
GList ** matches = user_data;
|
||||
*matches = g_list_prepend(*matches, t);
|
||||
}
|
||||
|
||||
LotList *
|
||||
xaccQueryGetLots (QofQuery * q, query_txn_match_t runtype)
|
||||
{
|
||||
GList * splits = qof_query_run(q);
|
||||
GList * current = NULL;
|
||||
GList * retval = NULL;
|
||||
GHashTable * lot_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
GNCLot * lot = NULL;
|
||||
gpointer val = NULL;
|
||||
int count = 0;
|
||||
|
||||
/* iterate over matching splits, incrementing a match-count in
|
||||
* the hash table */
|
||||
for (current = splits; current; current = current->next)
|
||||
{
|
||||
lot = xaccSplitGetLot((Split *)(current->data));
|
||||
|
||||
/* don't waste time looking up unless we need the count
|
||||
* information */
|
||||
if (runtype == QUERY_TXN_MATCH_ALL)
|
||||
{
|
||||
val = g_hash_table_lookup(lot_hash, lot);
|
||||
count = GPOINTER_TO_INT(val);
|
||||
}
|
||||
g_hash_table_insert(lot_hash, lot, GINT_TO_POINTER(count + 1));
|
||||
}
|
||||
|
||||
/* now pick out the transactions that match */
|
||||
if (runtype == QUERY_TXN_MATCH_ALL)
|
||||
{
|
||||
g_hash_table_foreach(lot_hash, query_match_all_lot_filter_func,
|
||||
&retval);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_hash_table_foreach(lot_hash, query_match_any_lot_filter_func,
|
||||
&retval);
|
||||
}
|
||||
|
||||
g_hash_table_destroy(lot_hash);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* match-adding API
|
||||
*******************************************************************/
|
||||
|
||||
void
|
||||
xaccQueryAddAccountMatch(QofQuery *q, AccountList *acct_list,
|
||||
QofGuidMatch how, QofQueryOp op)
|
||||
{
|
||||
GList *list = NULL;
|
||||
|
||||
if (!q) return;
|
||||
for (; acct_list; acct_list = acct_list->next)
|
||||
{
|
||||
Account *acc = acct_list->data;
|
||||
const GncGUID *guid;
|
||||
|
||||
if (!acc)
|
||||
{
|
||||
PWARN ("acct_list has NULL account");
|
||||
continue;
|
||||
}
|
||||
|
||||
guid = qof_entity_get_guid (QOF_INSTANCE(acc));
|
||||
if (!guid)
|
||||
{
|
||||
PWARN ("acct returns NULL GncGUID");
|
||||
continue;
|
||||
}
|
||||
|
||||
list = g_list_prepend (list, (gpointer)guid);
|
||||
}
|
||||
xaccQueryAddAccountGUIDMatch (q, list, how, op);
|
||||
g_list_free (list);
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddAccountGUIDMatch(QofQuery *q, AccountGUIDList *guid_list,
|
||||
QofGuidMatch how, QofQueryOp op)
|
||||
{
|
||||
QofQueryPredData *pred_data;
|
||||
GSList *param_list = NULL;
|
||||
|
||||
if (!q) return;
|
||||
|
||||
if (!guid_list && how != QOF_GUID_MATCH_NULL)
|
||||
{
|
||||
g_warning("Got a NULL guid_list but the QofGuidMatch is not MATCH_NULL (but instead %d). In other words, the list of GUID matches is empty but it must contain something non-empty.", how);
|
||||
/* qof_query_guid_predicate() would trigger a g_warning as well */
|
||||
return;
|
||||
}
|
||||
pred_data = qof_query_guid_predicate (how, guid_list);
|
||||
if (!pred_data)
|
||||
return;
|
||||
|
||||
switch (how)
|
||||
{
|
||||
case QOF_GUID_MATCH_ANY:
|
||||
case QOF_GUID_MATCH_NONE:
|
||||
param_list = qof_query_build_param_list (SPLIT_ACCOUNT, QOF_PARAM_GUID, NULL);
|
||||
break;
|
||||
case QOF_GUID_MATCH_ALL:
|
||||
param_list = qof_query_build_param_list (SPLIT_TRANS, TRANS_SPLITLIST,
|
||||
SPLIT_ACCOUNT_GUID, NULL);
|
||||
break;
|
||||
default:
|
||||
PERR ("Invalid match type: %d", how);
|
||||
break;
|
||||
}
|
||||
|
||||
qof_query_add_term (q, param_list, pred_data, op);
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddSingleAccountMatch(QofQuery *q, Account *acc, QofQueryOp op)
|
||||
{
|
||||
GList *list;
|
||||
const GncGUID *guid;
|
||||
|
||||
if (!q || !acc)
|
||||
return;
|
||||
|
||||
guid = qof_entity_get_guid (QOF_INSTANCE(acc));
|
||||
g_return_if_fail (guid);
|
||||
|
||||
list = g_list_prepend (NULL, (gpointer)guid);
|
||||
xaccQueryAddAccountGUIDMatch (q, list, QOF_GUID_MATCH_ANY, op);
|
||||
g_list_free (list);
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddStringMatch (QofQuery* q, const char *matchstring,
|
||||
gboolean case_sens, gboolean use_regexp,
|
||||
QofQueryCompare how, QofQueryOp op,
|
||||
const char * path, ...)
|
||||
{
|
||||
QofQueryPredData *pred_data;
|
||||
GSList *param_list;
|
||||
va_list ap;
|
||||
|
||||
if (!path || !q)
|
||||
return;
|
||||
|
||||
pred_data = qof_query_string_predicate (how, (char *)matchstring,
|
||||
(case_sens ? QOF_STRING_MATCH_NORMAL :
|
||||
QOF_STRING_MATCH_CASEINSENSITIVE),
|
||||
use_regexp);
|
||||
if (!pred_data)
|
||||
return;
|
||||
|
||||
va_start (ap, path);
|
||||
param_list = build_param_list_internal (path, ap);
|
||||
va_end (ap);
|
||||
|
||||
qof_query_add_term (q, param_list, pred_data, op);
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddNumericMatch (QofQuery *q, gnc_numeric amount, QofNumericMatch sign,
|
||||
QofQueryCompare how, QofQueryOp op,
|
||||
const char * path, ...)
|
||||
{
|
||||
QofQueryPredData *pred_data;
|
||||
GSList *param_list;
|
||||
va_list ap;
|
||||
|
||||
if (!q || !path)
|
||||
return;
|
||||
|
||||
pred_data = qof_query_numeric_predicate (how, sign, amount);
|
||||
if (!pred_data)
|
||||
return;
|
||||
|
||||
va_start (ap, path);
|
||||
param_list = build_param_list_internal (path, ap);
|
||||
va_end (ap);
|
||||
|
||||
qof_query_add_term (q, param_list, pred_data, op);
|
||||
}
|
||||
|
||||
/* The DateMatch queries match transactions whose posted date
|
||||
* is in a date range. If use_start is TRUE, then a matching
|
||||
* posted date will be greater than the start date. If
|
||||
* use_end is TRUE, then a match occurs for posted dates earlier
|
||||
* than the end date. If both flags are set, then *both*
|
||||
* conditions must hold ('and'). If neither flag is set, then
|
||||
* all transactions are matched.
|
||||
*/
|
||||
|
||||
void
|
||||
xaccQueryAddDateMatchTS (QofQuery * q,
|
||||
gboolean use_start, Timespec sts,
|
||||
gboolean use_end, Timespec ets,
|
||||
QofQueryOp op)
|
||||
{
|
||||
QofQuery *tmp_q = NULL;
|
||||
QofQueryPredData *pred_data;
|
||||
GSList *param_list;
|
||||
|
||||
if (!q || (!use_start && !use_end))
|
||||
return;
|
||||
|
||||
tmp_q = qof_query_create ();
|
||||
|
||||
if (use_start)
|
||||
{
|
||||
pred_data = qof_query_date_predicate (QOF_COMPARE_GTE, QOF_DATE_MATCH_NORMAL, sts);
|
||||
if (!pred_data)
|
||||
{
|
||||
qof_query_destroy (tmp_q);
|
||||
return;
|
||||
}
|
||||
|
||||
param_list = qof_query_build_param_list (SPLIT_TRANS, TRANS_DATE_POSTED, NULL);
|
||||
qof_query_add_term (tmp_q, param_list, pred_data, QOF_QUERY_AND);
|
||||
}
|
||||
|
||||
if (use_end)
|
||||
{
|
||||
pred_data = qof_query_date_predicate (QOF_COMPARE_LTE, QOF_DATE_MATCH_NORMAL, ets);
|
||||
if (!pred_data)
|
||||
{
|
||||
qof_query_destroy (tmp_q);
|
||||
return;
|
||||
}
|
||||
|
||||
param_list = qof_query_build_param_list (SPLIT_TRANS, TRANS_DATE_POSTED, NULL);
|
||||
qof_query_add_term (tmp_q, param_list, pred_data, QOF_QUERY_AND);
|
||||
}
|
||||
|
||||
qof_query_merge_in_place (q, tmp_q, op);
|
||||
qof_query_destroy (tmp_q);
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryGetDateMatchTS (QofQuery * q,
|
||||
Timespec * sts,
|
||||
Timespec * ets)
|
||||
{
|
||||
QofQueryPredData *term_data;
|
||||
GSList *param_list;
|
||||
GSList *terms, *tmp;
|
||||
|
||||
sts->tv_sec = sts->tv_nsec = 0;
|
||||
ets->tv_sec = ets->tv_nsec = 0;
|
||||
|
||||
param_list = qof_query_build_param_list (SPLIT_TRANS, TRANS_DATE_POSTED, NULL);
|
||||
terms = qof_query_get_term_type (q, param_list);
|
||||
g_slist_free(param_list);
|
||||
|
||||
for (tmp = terms; tmp; tmp = g_slist_next(tmp))
|
||||
{
|
||||
term_data = tmp->data;
|
||||
if (term_data->how == QOF_COMPARE_GTE)
|
||||
qof_query_date_predicate_get_date(term_data, sts);
|
||||
if (term_data->how == QOF_COMPARE_LTE)
|
||||
qof_query_date_predicate_get_date(term_data, ets);
|
||||
}
|
||||
g_slist_free(terms);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* xaccQueryAddDateMatch
|
||||
* Add a date filter to an existing query.
|
||||
********************************************************************/
|
||||
|
||||
void
|
||||
xaccQueryAddDateMatch(QofQuery * q,
|
||||
gboolean use_start, int sday, int smonth, int syear,
|
||||
gboolean use_end, int eday, int emonth, int eyear,
|
||||
QofQueryOp op)
|
||||
{
|
||||
/* gcc -O3 will auto-inline this function, avoiding a call overhead */
|
||||
xaccQueryAddDateMatchTS (q, use_start,
|
||||
gnc_dmy2timespec(sday, smonth, syear),
|
||||
use_end,
|
||||
gnc_dmy2timespec_end(eday, emonth, eyear),
|
||||
op);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* xaccQueryAddDateMatchTT
|
||||
* Add a date filter to an existing query.
|
||||
********************************************************************/
|
||||
|
||||
void
|
||||
xaccQueryAddDateMatchTT(QofQuery * q,
|
||||
gboolean use_start,
|
||||
time64 stt,
|
||||
gboolean use_end,
|
||||
time64 ett,
|
||||
QofQueryOp op)
|
||||
{
|
||||
Timespec sts;
|
||||
Timespec ets;
|
||||
|
||||
sts.tv_sec = stt;
|
||||
sts.tv_nsec = 0;
|
||||
|
||||
ets.tv_sec = ett;
|
||||
ets.tv_nsec = 0;
|
||||
|
||||
/* gcc -O3 will auto-inline this function, avoiding a call overhead */
|
||||
xaccQueryAddDateMatchTS (q, use_start, sts,
|
||||
use_end, ets, op);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryGetDateMatchTT (QofQuery * q,
|
||||
time64 * stt,
|
||||
time64 * ett)
|
||||
{
|
||||
Timespec sts;
|
||||
Timespec ets;
|
||||
|
||||
xaccQueryGetDateMatchTS (q, &sts, &ets);
|
||||
|
||||
*stt = sts.tv_sec;
|
||||
*ett = ets.tv_sec;
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddClearedMatch(QofQuery * q, cleared_match_t how, QofQueryOp op)
|
||||
{
|
||||
QofQueryPredData *pred_data;
|
||||
GSList *param_list;
|
||||
char chars[6];
|
||||
int i = 0;
|
||||
|
||||
if (!q)
|
||||
return;
|
||||
|
||||
if (how & CLEARED_CLEARED)
|
||||
chars[i++] = CREC;
|
||||
if (how & CLEARED_RECONCILED)
|
||||
chars[i++] = YREC;
|
||||
if (how & CLEARED_FROZEN)
|
||||
chars[i++] = FREC;
|
||||
if (how & CLEARED_NO)
|
||||
chars[i++] = NREC;
|
||||
if (how & CLEARED_VOIDED)
|
||||
chars[i++] = VREC;
|
||||
chars[i] = '\0';
|
||||
|
||||
pred_data = qof_query_char_predicate (QOF_CHAR_MATCH_ANY, chars);
|
||||
if (!pred_data)
|
||||
return;
|
||||
|
||||
param_list = qof_query_build_param_list (SPLIT_RECONCILE, NULL);
|
||||
|
||||
qof_query_add_term (q, param_list, pred_data, op);
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddGUIDMatch(QofQuery * q, const GncGUID *guid,
|
||||
QofIdType id_type, QofQueryOp op)
|
||||
{
|
||||
GSList *param_list = NULL;
|
||||
|
||||
if (!q || !guid || !id_type)
|
||||
return;
|
||||
|
||||
if (!g_strcmp0 (id_type, GNC_ID_SPLIT))
|
||||
param_list = qof_query_build_param_list (QOF_PARAM_GUID, NULL);
|
||||
else if (!g_strcmp0 (id_type, GNC_ID_TRANS))
|
||||
param_list = qof_query_build_param_list (SPLIT_TRANS, QOF_PARAM_GUID, NULL);
|
||||
else if (!g_strcmp0 (id_type, GNC_ID_ACCOUNT))
|
||||
param_list = qof_query_build_param_list (SPLIT_ACCOUNT, QOF_PARAM_GUID, NULL);
|
||||
else
|
||||
PERR ("Invalid match type: %s", id_type);
|
||||
|
||||
qof_query_add_guid_match (q, param_list, guid, op);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* xaccQueryAddClosingTransMatch
|
||||
* Add a filter that matches book closing entries to an existing query.
|
||||
********************************************************************/
|
||||
|
||||
void
|
||||
xaccQueryAddClosingTransMatch(QofQuery *q, gboolean value, QofQueryOp op)
|
||||
{
|
||||
GSList *param_list;
|
||||
|
||||
param_list = qof_query_build_param_list(SPLIT_TRANS, TRANS_IS_CLOSING, NULL);
|
||||
qof_query_add_boolean_match(q, param_list, value, op);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* xaccQueryGetEarliestDateFound
|
||||
*******************************************************************/
|
||||
|
||||
time64
|
||||
xaccQueryGetEarliestDateFound(QofQuery * q)
|
||||
{
|
||||
GList * spl;
|
||||
Split * sp;
|
||||
time64 earliest;
|
||||
|
||||
if (!q) return 0;
|
||||
spl = qof_query_last_run (q);
|
||||
if (!spl) return 0;
|
||||
|
||||
/* Safe until 2038 on archs where time64 is 32bit */
|
||||
sp = spl->data;
|
||||
earliest = sp->parent->date_posted.tv_sec;
|
||||
for (; spl; spl = spl->next)
|
||||
{
|
||||
sp = spl->data;
|
||||
if (sp->parent->date_posted.tv_sec < earliest)
|
||||
{
|
||||
earliest = sp->parent->date_posted.tv_sec;
|
||||
}
|
||||
}
|
||||
return earliest;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* xaccQueryGetLatestDateFound
|
||||
*******************************************************************/
|
||||
|
||||
time64
|
||||
xaccQueryGetLatestDateFound(QofQuery * q)
|
||||
{
|
||||
Split * sp;
|
||||
GList * spl;
|
||||
time64 latest = 0;
|
||||
|
||||
if (!q) return 0;
|
||||
spl = qof_query_last_run (q);
|
||||
if (!spl) return 0;
|
||||
|
||||
for (; spl; spl = spl->next)
|
||||
{
|
||||
sp = spl->data;
|
||||
if (sp->parent->date_posted.tv_sec > latest)
|
||||
{
|
||||
latest = sp->parent->date_posted.tv_sec;
|
||||
}
|
||||
}
|
||||
return latest;
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddDescriptionMatch(QofQuery *q, const char *m, gboolean c, gboolean r,
|
||||
QofQueryCompare h, QofQueryOp o)
|
||||
{
|
||||
xaccQueryAddStringMatch ((q), (m), (c), (r), (h), (o), SPLIT_TRANS,
|
||||
TRANS_DESCRIPTION, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddNotesMatch(QofQuery *q, const char *m, gboolean c, gboolean r,
|
||||
QofQueryCompare h, QofQueryOp o)
|
||||
{
|
||||
xaccQueryAddStringMatch ((q), (m), (c), (r), (h), (o), SPLIT_TRANS,
|
||||
TRANS_NOTES, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddNumberMatch(QofQuery *q, const char *m, gboolean c, gboolean r,
|
||||
QofQueryCompare h, QofQueryOp o)
|
||||
{
|
||||
xaccQueryAddStringMatch ((q), (m), (c), (r), (h), (o), SPLIT_TRANS,
|
||||
TRANS_NUM, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddActionMatch(QofQuery *q, const char *m, gboolean c, gboolean r,
|
||||
QofQueryCompare h, QofQueryOp o)
|
||||
{
|
||||
xaccQueryAddStringMatch ((q), (m), (c), (r), (h), (o), SPLIT_ACTION, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddMemoMatch(QofQuery *q, const char *m, gboolean c, gboolean r,
|
||||
QofQueryCompare h, QofQueryOp o)
|
||||
{
|
||||
xaccQueryAddStringMatch ((q), (m), (c), (r), (h), (o), SPLIT_MEMO, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddValueMatch(QofQuery *q, gnc_numeric amt, QofNumericMatch sgn,
|
||||
QofQueryCompare how, QofQueryOp op)
|
||||
{
|
||||
xaccQueryAddNumericMatch ((q), (amt), (sgn), (how), (op),
|
||||
SPLIT_VALUE, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddSharePriceMatch(QofQuery *q, gnc_numeric amt, QofQueryCompare how,
|
||||
QofQueryOp op)
|
||||
{
|
||||
xaccQueryAddNumericMatch ((q), (amt), QOF_NUMERIC_MATCH_ANY, (how), (op),
|
||||
SPLIT_SHARE_PRICE, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddSharesMatch(QofQuery *q, gnc_numeric amt, QofQueryCompare how,
|
||||
QofQueryOp op)
|
||||
{
|
||||
xaccQueryAddNumericMatch ((q), (amt), QOF_NUMERIC_MATCH_ANY, (how), (op),
|
||||
SPLIT_AMOUNT, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
xaccQueryAddBalanceMatch(QofQuery *q, QofQueryCompare bal, QofQueryOp op)
|
||||
{
|
||||
xaccQueryAddNumericMatch(
|
||||
(q), gnc_numeric_zero(), QOF_NUMERIC_MATCH_ANY,
|
||||
((bal) ? QOF_COMPARE_EQUAL : QOF_COMPARE_NEQ), (op),
|
||||
SPLIT_TRANS, TRANS_IMBALANCE, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* ======================== END OF FILE ======================= */
|
||||
Reference in New Issue
Block a user