2001-08-07 23:36:04 +00:00
|
|
|
/********************************************************************\
|
|
|
|
|
* SchedXaction.c -- Scheduled Transaction implementation. *
|
|
|
|
|
* Copyright (C) 2001 Joshua Sled <jsled@asynchronous.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 *
|
|
|
|
|
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
|
|
|
|
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
|
|
|
|
* *
|
|
|
|
|
\********************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "FreqSpec.h"
|
2001-11-24 12:10:42 +00:00
|
|
|
#include "GNCId.h"
|
2001-11-24 18:22:57 +00:00
|
|
|
#include "Group.h"
|
2003-06-10 04:48:55 +00:00
|
|
|
#include "GroupP.h"
|
2003-06-10 15:21:47 +00:00
|
|
|
#include "SX-book.h"
|
2001-10-04 00:36:28 +00:00
|
|
|
#include "SX-ttinfo.h"
|
2001-10-09 08:26:03 +00:00
|
|
|
#include "SchedXactionP.h"
|
2001-11-24 18:22:57 +00:00
|
|
|
#include "Transaction.h"
|
2003-06-09 17:57:36 +00:00
|
|
|
#include "gnc-date.h"
|
2001-11-24 12:10:42 +00:00
|
|
|
#include "gnc-engine.h"
|
2001-08-07 23:36:04 +00:00
|
|
|
#include "gnc-engine-util.h"
|
|
|
|
|
#include "gnc-event-p.h"
|
|
|
|
|
#include "guid.h"
|
2001-10-04 00:36:28 +00:00
|
|
|
#include "messages.h"
|
2003-06-25 00:52:46 +00:00
|
|
|
#include "qofbook.h"
|
|
|
|
|
#include "qofbook-p.h"
|
2001-08-07 23:36:04 +00:00
|
|
|
|
|
|
|
|
static short module = MOD_SX;
|
|
|
|
|
|
|
|
|
|
/** Local Prototypes *****/
|
|
|
|
|
|
2002-04-16 07:09:16 +00:00
|
|
|
void sxprivtransactionListMapDelete( gpointer data, gpointer user_data );
|
2001-08-07 23:36:04 +00:00
|
|
|
|
|
|
|
|
static void
|
2003-06-25 00:52:46 +00:00
|
|
|
xaccSchedXactionInit( SchedXaction *sx, QofBook *book)
|
2001-08-07 23:36:04 +00:00
|
|
|
{
|
2003-06-10 15:21:47 +00:00
|
|
|
AccountGroup *ag;
|
|
|
|
|
char *name;
|
2001-10-04 00:36:28 +00:00
|
|
|
|
2003-06-25 00:52:46 +00:00
|
|
|
sx->entity_table = qof_book_get_entity_table (book);
|
2001-10-09 08:26:03 +00:00
|
|
|
|
2003-06-10 15:21:47 +00:00
|
|
|
sx->freq = xaccFreqSpecMalloc(book);
|
2001-08-07 23:36:04 +00:00
|
|
|
|
2003-06-10 15:21:47 +00:00
|
|
|
xaccGUIDNew( &sx->guid, book );
|
|
|
|
|
xaccStoreEntity( sx->entity_table, sx,
|
|
|
|
|
&sx->guid, GNC_ID_SCHEDXACTION );
|
|
|
|
|
g_date_clear( &sx->last_date, 1 );
|
|
|
|
|
g_date_clear( &sx->start_date, 1 );
|
|
|
|
|
g_date_clear( &sx->end_date, 1 );
|
2001-08-07 23:36:04 +00:00
|
|
|
|
2003-06-10 15:21:47 +00:00
|
|
|
sx->num_occurances_total = 0;
|
|
|
|
|
sx->kvp_data = kvp_frame_new();
|
|
|
|
|
sx->autoCreateOption = FALSE;
|
|
|
|
|
sx->autoCreateNotify = FALSE;
|
|
|
|
|
sx->advanceCreateDays = 0;
|
|
|
|
|
sx->advanceRemindDays = 0;
|
|
|
|
|
sx->instance_num = 0;
|
2001-08-07 23:36:04 +00:00
|
|
|
sx->dirty = TRUE;
|
2003-06-10 15:21:47 +00:00
|
|
|
sx->deferredList = NULL;
|
|
|
|
|
|
|
|
|
|
/* create a new template account for our splits */
|
|
|
|
|
sx->template_acct = xaccMallocAccount(book);
|
|
|
|
|
name = guid_to_string( &sx->guid );
|
|
|
|
|
xaccAccountSetName( sx->template_acct, name );
|
|
|
|
|
xaccAccountSetCommodity
|
|
|
|
|
(sx->template_acct,
|
|
|
|
|
gnc_commodity_new( "template", "template",
|
|
|
|
|
"template", "template", 1 ) );
|
2001-08-07 23:36:04 +00:00
|
|
|
g_free( name );
|
2003-06-10 15:21:47 +00:00
|
|
|
xaccAccountSetType( sx->template_acct, BANK );
|
|
|
|
|
ag = gnc_book_get_template_group( book );
|
|
|
|
|
xaccGroupInsertAccount( ag, sx->template_acct );
|
2001-08-07 23:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SchedXaction*
|
2003-06-25 00:52:46 +00:00
|
|
|
xaccSchedXactionMalloc(QofBook *book)
|
2001-08-07 23:36:04 +00:00
|
|
|
{
|
2003-06-10 15:21:47 +00:00
|
|
|
SchedXaction *sx;
|
2001-10-04 00:36:28 +00:00
|
|
|
|
2003-06-10 15:21:47 +00:00
|
|
|
g_return_val_if_fail (book, NULL);
|
2001-10-04 00:36:28 +00:00
|
|
|
|
2003-06-10 15:21:47 +00:00
|
|
|
sx = g_new0( SchedXaction, 1 );
|
|
|
|
|
xaccSchedXactionInit( sx, book );
|
|
|
|
|
gnc_engine_generate_event( &sx->guid, GNC_EVENT_CREATE );
|
2001-10-04 00:36:28 +00:00
|
|
|
|
2003-06-10 15:21:47 +00:00
|
|
|
return sx;
|
2001-08-07 23:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
2001-08-20 21:30:58 +00:00
|
|
|
static void
|
2001-08-15 05:17:33 +00:00
|
|
|
sxprivTransMapDelete( gpointer data, gpointer user_data )
|
2001-08-07 23:36:04 +00:00
|
|
|
{
|
2001-08-15 05:17:33 +00:00
|
|
|
Transaction *t = (Transaction *) data;
|
2001-08-07 23:36:04 +00:00
|
|
|
xaccTransBeginEdit( t );
|
|
|
|
|
xaccTransDestroy( t );
|
|
|
|
|
xaccTransCommitEdit( t );
|
2001-08-15 05:17:33 +00:00
|
|
|
return;
|
2001-08-07 23:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
2001-08-30 06:24:55 +00:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
delete_template_trans(SchedXaction *sx)
|
|
|
|
|
{
|
|
|
|
|
GList *templ_acct_splits, *curr_split_listref;
|
|
|
|
|
Split *curr_split;
|
|
|
|
|
Transaction *split_trans;
|
|
|
|
|
GList *templ_acct_transactions = NULL;
|
|
|
|
|
|
|
|
|
|
templ_acct_splits
|
|
|
|
|
= xaccAccountGetSplitList(sx->template_acct);
|
|
|
|
|
|
|
|
|
|
for(curr_split_listref = templ_acct_splits;
|
|
|
|
|
curr_split_listref;
|
|
|
|
|
curr_split_listref = curr_split_listref->next)
|
|
|
|
|
{
|
|
|
|
|
curr_split = (Split *) curr_split_listref->data;
|
|
|
|
|
split_trans = xaccSplitGetParent(curr_split);
|
|
|
|
|
if(! (g_list_find(templ_acct_transactions, split_trans)))
|
|
|
|
|
{
|
|
|
|
|
templ_acct_transactions
|
|
|
|
|
= g_list_prepend(templ_acct_transactions, split_trans);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_list_foreach(templ_acct_transactions,
|
|
|
|
|
sxprivTransMapDelete,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
2001-08-07 23:36:04 +00:00
|
|
|
void
|
|
|
|
|
xaccSchedXactionFree( SchedXaction *sx )
|
|
|
|
|
{
|
2002-10-06 22:31:05 +00:00
|
|
|
GList *l;
|
2001-08-07 23:36:04 +00:00
|
|
|
|
2001-08-30 06:24:55 +00:00
|
|
|
if ( sx == NULL ) return;
|
|
|
|
|
|
|
|
|
|
xaccFreqSpecFree( sx->freq );
|
|
|
|
|
gnc_engine_generate_event( &sx->guid, GNC_EVENT_DESTROY );
|
2001-10-09 08:26:03 +00:00
|
|
|
xaccRemoveEntity( sx->entity_table, &sx->guid );
|
2001-08-30 06:24:55 +00:00
|
|
|
|
|
|
|
|
if ( sx->name )
|
|
|
|
|
g_free( sx->name );
|
2001-10-09 08:26:03 +00:00
|
|
|
|
2001-08-30 06:24:55 +00:00
|
|
|
/*
|
|
|
|
|
* we have to delete the transactions in the
|
|
|
|
|
* template account ourselves
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
delete_template_trans( sx );
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* xaccAccountDestroy removes the account from
|
|
|
|
|
* its group for us AFAICT
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
xaccAccountBeginEdit(sx->template_acct);
|
|
|
|
|
xaccAccountDestroy(sx->template_acct);
|
2002-10-06 22:31:05 +00:00
|
|
|
|
|
|
|
|
for ( l = sx->deferredList; l; l = l->next ) {
|
|
|
|
|
gnc_sx_destroy_temporal_state( l->data );
|
|
|
|
|
l->data = NULL;
|
|
|
|
|
}
|
|
|
|
|
if ( sx->deferredList ) {
|
|
|
|
|
g_list_free( sx->deferredList );
|
|
|
|
|
sx->deferredList = NULL;
|
|
|
|
|
}
|
2001-08-30 06:24:55 +00:00
|
|
|
|
|
|
|
|
g_free( sx );
|
|
|
|
|
|
2002-10-06 22:31:05 +00:00
|
|
|
return;
|
2001-08-07 23:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FreqSpec *
|
|
|
|
|
xaccSchedXactionGetFreqSpec( SchedXaction *sx )
|
|
|
|
|
{
|
|
|
|
|
return sx->freq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetFreqSpec( SchedXaction *sx, FreqSpec *fs )
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail( fs );
|
|
|
|
|
|
|
|
|
|
xaccFreqSpecFree( sx->freq );
|
|
|
|
|
sx->freq = fs;
|
|
|
|
|
sx->dirty = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gchar *
|
|
|
|
|
xaccSchedXactionGetName( SchedXaction *sx )
|
|
|
|
|
{
|
2003-06-10 15:21:47 +00:00
|
|
|
return sx->name;
|
2001-08-07 23:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetName( SchedXaction *sx, const gchar *newName )
|
|
|
|
|
{
|
2003-06-10 15:21:47 +00:00
|
|
|
g_return_if_fail( newName != NULL );
|
|
|
|
|
if ( sx->name != NULL ) {
|
|
|
|
|
g_free( sx->name );
|
|
|
|
|
sx->name = NULL;
|
|
|
|
|
}
|
2001-08-07 23:36:04 +00:00
|
|
|
sx->dirty = TRUE;
|
2003-06-10 15:21:47 +00:00
|
|
|
sx->name = g_strdup( newName );
|
2001-08-07 23:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GDate*
|
|
|
|
|
xaccSchedXactionGetStartDate( SchedXaction *sx )
|
|
|
|
|
{
|
2003-06-10 15:21:47 +00:00
|
|
|
return &sx->start_date;
|
2001-08-07 23:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetStartDate( SchedXaction *sx, GDate* newStart )
|
|
|
|
|
{
|
2003-06-10 15:21:47 +00:00
|
|
|
sx->start_date = *newStart;
|
2001-08-07 23:36:04 +00:00
|
|
|
sx->dirty = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
xaccSchedXactionHasEndDate( SchedXaction *sx )
|
|
|
|
|
{
|
2003-06-10 15:21:47 +00:00
|
|
|
return g_date_valid( &sx->end_date );
|
2001-08-07 23:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GDate*
|
|
|
|
|
xaccSchedXactionGetEndDate( SchedXaction *sx )
|
|
|
|
|
{
|
2003-06-10 15:21:47 +00:00
|
|
|
return &sx->end_date;
|
2001-08-07 23:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetEndDate( SchedXaction *sx, GDate *newEnd )
|
|
|
|
|
{
|
2001-10-29 10:08:11 +00:00
|
|
|
if ( g_date_valid( newEnd )
|
|
|
|
|
&& g_date_compare( newEnd, &sx->start_date ) < 0 ) {
|
|
|
|
|
/* XXX: I reject the bad data - is this the right
|
|
|
|
|
* thing to do <rgmerk>.
|
|
|
|
|
* This warning is only human readable - the caller
|
|
|
|
|
* doesn't know the call failed. This is bad
|
|
|
|
|
*/
|
|
|
|
|
PWARN( "New end date before start date" );
|
|
|
|
|
return;
|
2001-08-07 23:36:04 +00:00
|
|
|
}
|
2001-10-29 10:08:11 +00:00
|
|
|
|
|
|
|
|
sx->end_date = *newEnd;
|
|
|
|
|
sx->dirty = TRUE;
|
2001-08-07 23:36:04 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GDate*
|
|
|
|
|
xaccSchedXactionGetLastOccurDate( SchedXaction *sx )
|
|
|
|
|
{
|
2003-06-10 15:21:47 +00:00
|
|
|
return &sx->last_date;
|
2001-08-07 23:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetLastOccurDate( SchedXaction *sx, GDate* newLastOccur )
|
|
|
|
|
{
|
|
|
|
|
sx->last_date = *newLastOccur;
|
|
|
|
|
sx->dirty = TRUE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
xaccSchedXactionHasOccurDef( SchedXaction *sx )
|
|
|
|
|
{
|
|
|
|
|
return ( xaccSchedXactionGetNumOccur( sx ) != 0 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gint
|
|
|
|
|
xaccSchedXactionGetNumOccur( SchedXaction *sx )
|
|
|
|
|
{
|
|
|
|
|
return sx->num_occurances_total;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetNumOccur( SchedXaction *sx, gint newNum )
|
|
|
|
|
{
|
|
|
|
|
sx->num_occurances_remain = sx->num_occurances_total = newNum;
|
|
|
|
|
sx->dirty = TRUE;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gint
|
|
|
|
|
xaccSchedXactionGetRemOccur( SchedXaction *sx )
|
|
|
|
|
{
|
|
|
|
|
return sx->num_occurances_remain;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetRemOccur( SchedXaction *sx,
|
|
|
|
|
gint numRemain )
|
|
|
|
|
{
|
|
|
|
|
/* FIXME This condition can be tightened up */
|
|
|
|
|
if ( numRemain > sx->num_occurances_total ) {
|
2001-10-29 10:08:11 +00:00
|
|
|
PWARN("The number remaining is greater than the total occurrences");
|
2001-08-07 23:36:04 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sx->num_occurances_remain = numRemain;
|
|
|
|
|
sx->dirty = TRUE;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
kvp_value *
|
|
|
|
|
xaccSchedXactionGetSlot( SchedXaction *sx, const char *slot )
|
|
|
|
|
{
|
|
|
|
|
if (!sx)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return kvp_frame_get_slot(sx->kvp_data, slot);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetSlot( SchedXaction *sx,
|
|
|
|
|
const char *slot,
|
|
|
|
|
const kvp_value *value )
|
|
|
|
|
{
|
|
|
|
|
if (!sx)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kvp_frame_set_slot( sx->kvp_data, slot, value );
|
|
|
|
|
sx->dirty = TRUE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kvp_frame*
|
|
|
|
|
xaccSchedXactionGetSlots( SchedXaction *sx )
|
|
|
|
|
{
|
2003-06-10 15:21:47 +00:00
|
|
|
return sx->kvp_data;
|
2001-08-07 23:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetSlots( SchedXaction *sx, kvp_frame *frm )
|
|
|
|
|
{
|
|
|
|
|
sx->kvp_data = frm;
|
|
|
|
|
sx->dirty = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const GUID*
|
|
|
|
|
xaccSchedXactionGetGUID( SchedXaction *sx )
|
|
|
|
|
{
|
|
|
|
|
return &sx->guid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetGUID( SchedXaction *sx, GUID g )
|
|
|
|
|
{
|
|
|
|
|
sx->guid = g;
|
|
|
|
|
sx->dirty = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionGetAutoCreate( SchedXaction *sx,
|
|
|
|
|
gboolean *outAutoCreate,
|
|
|
|
|
gboolean *outNotify )
|
|
|
|
|
{
|
|
|
|
|
*outAutoCreate = sx->autoCreateOption;
|
|
|
|
|
*outNotify = sx->autoCreateNotify;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetAutoCreate( SchedXaction *sx,
|
|
|
|
|
gboolean newAutoCreate,
|
|
|
|
|
gboolean newNotify )
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
sx->autoCreateOption = newAutoCreate;
|
|
|
|
|
sx->autoCreateNotify = newNotify;
|
|
|
|
|
sx->dirty = TRUE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gint
|
|
|
|
|
xaccSchedXactionGetAdvanceCreation( SchedXaction *sx )
|
|
|
|
|
{
|
|
|
|
|
return sx->advanceCreateDays;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetAdvanceCreation( SchedXaction *sx, gint createDays )
|
|
|
|
|
{
|
|
|
|
|
sx->advanceCreateDays = createDays;
|
|
|
|
|
sx->dirty = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gint
|
|
|
|
|
xaccSchedXactionGetAdvanceReminder( SchedXaction *sx )
|
|
|
|
|
{
|
|
|
|
|
return sx->advanceRemindDays;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetAdvanceReminder( SchedXaction *sx, gint reminderDays )
|
|
|
|
|
{
|
|
|
|
|
sx->dirty = TRUE;
|
|
|
|
|
sx->advanceRemindDays = reminderDays;
|
|
|
|
|
}
|
|
|
|
|
|
2001-09-04 07:26:41 +00:00
|
|
|
|
2001-08-07 23:36:04 +00:00
|
|
|
GDate
|
2001-10-22 09:17:34 +00:00
|
|
|
xaccSchedXactionGetNextInstance( SchedXaction *sx, void *stateData )
|
2001-08-07 23:36:04 +00:00
|
|
|
{
|
|
|
|
|
GDate last_occur, next_occur, tmpDate;
|
|
|
|
|
|
|
|
|
|
g_date_clear( &last_occur, 1 );
|
|
|
|
|
g_date_clear( &next_occur, 1 );
|
|
|
|
|
g_date_clear( &tmpDate, 1 );
|
|
|
|
|
|
|
|
|
|
if ( g_date_valid( &sx->last_date ) ) {
|
|
|
|
|
last_occur = sx->last_date;
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-29 20:44:54 +00:00
|
|
|
if ( stateData != NULL ) {
|
|
|
|
|
temporalStateData *tsd = (temporalStateData*)stateData;
|
2003-01-26 02:53:58 +00:00
|
|
|
last_occur = tsd->last_date;
|
2002-09-29 20:44:54 +00:00
|
|
|
}
|
|
|
|
|
|
2001-08-07 23:36:04 +00:00
|
|
|
if ( g_date_valid( &sx->start_date ) ) {
|
|
|
|
|
if ( g_date_valid(&last_occur) ) {
|
|
|
|
|
last_occur =
|
|
|
|
|
( g_date_compare( &last_occur,
|
|
|
|
|
&sx->start_date ) > 0 ?
|
|
|
|
|
last_occur : sx->start_date );
|
|
|
|
|
} else {
|
2002-09-29 20:44:54 +00:00
|
|
|
/* Think about this for a second, and you realize that if the
|
|
|
|
|
* start date is _today_, we need a last-occur date such that
|
|
|
|
|
* the 'next instance' is after that date, and equal to the
|
|
|
|
|
* start date... one day should be good.
|
|
|
|
|
*
|
|
|
|
|
* This only holds for the first instance [read: if the
|
2003-01-26 02:53:58 +00:00
|
|
|
* last[-occur]_date is invalid] */
|
2001-08-07 23:36:04 +00:00
|
|
|
last_occur = sx->start_date;
|
2002-09-29 20:44:54 +00:00
|
|
|
g_date_subtract_days( &last_occur, 1 );
|
2001-08-07 23:36:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
xaccFreqSpecGetNextInstance( sx->freq, &last_occur, &next_occur );
|
2001-10-22 09:17:34 +00:00
|
|
|
|
|
|
|
|
/* out-of-bounds check */
|
|
|
|
|
if ( xaccSchedXactionHasEndDate( sx ) ) {
|
|
|
|
|
GDate *end_date = xaccSchedXactionGetEndDate( sx );
|
|
|
|
|
if ( g_date_compare( &next_occur, end_date ) > 0 ) {
|
|
|
|
|
PINFO( "next_occur past end date" );
|
|
|
|
|
g_date_clear( &next_occur, 1 );
|
|
|
|
|
}
|
2002-09-29 20:44:54 +00:00
|
|
|
} else if ( xaccSchedXactionHasOccurDef( sx ) ) {
|
|
|
|
|
if ( stateData ) {
|
|
|
|
|
temporalStateData *tsd = (temporalStateData*)stateData;
|
|
|
|
|
if ( tsd->num_occur_rem == 0 ) {
|
|
|
|
|
PINFO( "no more occurances remain" );
|
|
|
|
|
g_date_clear( &next_occur, 1 );
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if ( sx->num_occurances_remain == 0 ) {
|
|
|
|
|
g_date_clear( &next_occur, 1 );
|
|
|
|
|
}
|
2001-10-22 09:17:34 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-07 23:36:04 +00:00
|
|
|
return next_occur;
|
|
|
|
|
}
|
|
|
|
|
|
2001-10-22 09:17:34 +00:00
|
|
|
GDate
|
|
|
|
|
xaccSchedXactionGetInstanceAfter( SchedXaction *sx,
|
|
|
|
|
GDate *date,
|
|
|
|
|
void *stateData )
|
2001-08-07 23:36:04 +00:00
|
|
|
{
|
2002-09-29 20:44:54 +00:00
|
|
|
GDate prev_occur, next_occur;
|
|
|
|
|
|
2002-10-06 22:31:05 +00:00
|
|
|
g_date_clear( &prev_occur, 1 );
|
|
|
|
|
if ( date ) {
|
|
|
|
|
prev_occur = *date;
|
|
|
|
|
}
|
2002-09-29 20:44:54 +00:00
|
|
|
|
|
|
|
|
if ( stateData != NULL ) {
|
|
|
|
|
temporalStateData *tsd = (temporalStateData*)stateData;
|
|
|
|
|
prev_occur = tsd->last_date;
|
|
|
|
|
}
|
2002-10-06 22:31:05 +00:00
|
|
|
|
2002-09-29 20:44:54 +00:00
|
|
|
if ( ! g_date_valid( &prev_occur ) ) {
|
|
|
|
|
/* We must be at the beginning. */
|
|
|
|
|
prev_occur = sx->start_date;
|
|
|
|
|
g_date_subtract_days( &prev_occur, 1 );
|
|
|
|
|
}
|
2001-10-22 09:17:34 +00:00
|
|
|
|
2002-09-29 20:44:54 +00:00
|
|
|
xaccFreqSpecGetNextInstance( sx->freq, &prev_occur, &next_occur );
|
2001-10-22 09:17:34 +00:00
|
|
|
|
|
|
|
|
if ( xaccSchedXactionHasEndDate( sx ) ) {
|
|
|
|
|
GDate *end_date;
|
|
|
|
|
|
|
|
|
|
end_date = xaccSchedXactionGetEndDate( sx );
|
|
|
|
|
if ( g_date_compare( &next_occur, end_date ) > 0 ) {
|
|
|
|
|
g_date_clear( &next_occur, 1 );
|
|
|
|
|
}
|
2002-09-29 20:44:54 +00:00
|
|
|
} else if ( xaccSchedXactionHasOccurDef( sx ) ) {
|
|
|
|
|
if ( stateData ) {
|
|
|
|
|
temporalStateData *tsd = (temporalStateData*)stateData;
|
|
|
|
|
if ( tsd->num_occur_rem == 0 ) {
|
|
|
|
|
g_date_clear( &next_occur, 1 );
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if ( sx->num_occurances_remain == 0 ) {
|
|
|
|
|
g_date_clear( &next_occur, 1 );
|
|
|
|
|
}
|
2001-10-22 09:17:34 +00:00
|
|
|
}
|
|
|
|
|
}
|
2001-08-07 23:36:04 +00:00
|
|
|
return next_occur;
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-24 22:04:57 +00:00
|
|
|
gint
|
|
|
|
|
gnc_sx_get_instance_count( SchedXaction *sx, void *stateData )
|
|
|
|
|
{
|
|
|
|
|
gint toRet = -1;
|
|
|
|
|
temporalStateData *tsd;
|
|
|
|
|
|
|
|
|
|
if ( stateData ) {
|
|
|
|
|
tsd = (temporalStateData*)stateData;
|
|
|
|
|
toRet = tsd->num_inst;
|
|
|
|
|
} else {
|
|
|
|
|
toRet = sx->instance_num;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return toRet;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
gnc_sx_set_instance_count( SchedXaction *sx, gint instanceNum )
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail( sx );
|
|
|
|
|
sx->instance_num = instanceNum;
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-07 23:36:04 +00:00
|
|
|
GList *
|
|
|
|
|
xaccSchedXactionGetSplits( SchedXaction *sx )
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail( sx, NULL );
|
|
|
|
|
return xaccAccountGetSplitList(sx->template_acct);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetDirtyness( SchedXaction *sx, gboolean dirty_p)
|
|
|
|
|
{
|
|
|
|
|
sx->dirty = dirty_p;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
xaccSchedXactionIsDirty(SchedXaction *sx)
|
|
|
|
|
{
|
|
|
|
|
return sx->dirty;
|
|
|
|
|
}
|
2001-08-30 06:24:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
static Split *
|
2001-10-05 08:35:04 +00:00
|
|
|
pack_split_info (TTSplitInfo *s_info, Account *parent_acct,
|
2003-06-25 00:52:46 +00:00
|
|
|
Transaction *parent_trans, QofBook *book)
|
2001-08-30 06:24:55 +00:00
|
|
|
{
|
|
|
|
|
Split *split;
|
2001-12-06 09:30:25 +00:00
|
|
|
kvp_frame *split_frame;
|
2001-08-30 06:24:55 +00:00
|
|
|
kvp_value *tmp_value;
|
|
|
|
|
const GUID *acc_guid;
|
|
|
|
|
|
2001-11-24 12:10:42 +00:00
|
|
|
split = xaccMallocSplit(book);
|
2001-08-30 06:24:55 +00:00
|
|
|
|
|
|
|
|
xaccSplitSetMemo(split,
|
|
|
|
|
gnc_ttsplitinfo_get_memo(s_info));
|
|
|
|
|
|
|
|
|
|
xaccSplitSetAction(split,
|
|
|
|
|
gnc_ttsplitinfo_get_action(s_info));
|
|
|
|
|
|
|
|
|
|
|
2001-09-21 06:23:06 +00:00
|
|
|
xaccAccountInsertSplit(parent_acct,
|
|
|
|
|
split);
|
|
|
|
|
|
2001-08-30 06:24:55 +00:00
|
|
|
split_frame = xaccSplitGetSlots(split);
|
|
|
|
|
|
|
|
|
|
tmp_value
|
|
|
|
|
= kvp_value_new_string(gnc_ttsplitinfo_get_credit_formula(s_info));
|
|
|
|
|
|
|
|
|
|
kvp_frame_set_slot_path(split_frame,
|
|
|
|
|
tmp_value,
|
2001-09-04 07:26:41 +00:00
|
|
|
GNC_SX_ID,
|
2001-09-05 07:35:20 +00:00
|
|
|
GNC_SX_CREDIT_FORMULA,
|
|
|
|
|
NULL);
|
2001-08-30 06:24:55 +00:00
|
|
|
kvp_value_delete(tmp_value);
|
|
|
|
|
|
|
|
|
|
tmp_value
|
|
|
|
|
= kvp_value_new_string(gnc_ttsplitinfo_get_debit_formula(s_info));
|
|
|
|
|
|
|
|
|
|
kvp_frame_set_slot_path(split_frame,
|
|
|
|
|
tmp_value,
|
2001-09-04 07:26:41 +00:00
|
|
|
GNC_SX_ID,
|
2001-09-05 07:35:20 +00:00
|
|
|
GNC_SX_DEBIT_FORMULA,
|
|
|
|
|
NULL);
|
2001-08-30 06:24:55 +00:00
|
|
|
|
|
|
|
|
kvp_value_delete(tmp_value);
|
|
|
|
|
|
|
|
|
|
acc_guid = xaccAccountGetGUID(gnc_ttsplitinfo_get_account(s_info));
|
|
|
|
|
|
|
|
|
|
tmp_value = kvp_value_new_guid(acc_guid);
|
|
|
|
|
|
|
|
|
|
kvp_frame_set_slot_path(split_frame,
|
2001-09-05 07:35:20 +00:00
|
|
|
tmp_value,
|
|
|
|
|
GNC_SX_ID,
|
|
|
|
|
GNC_SX_ACCOUNT,
|
|
|
|
|
NULL);
|
2001-08-30 06:24:55 +00:00
|
|
|
|
|
|
|
|
kvp_value_delete(tmp_value);
|
|
|
|
|
|
|
|
|
|
return split;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-10-04 08:17:14 +00:00
|
|
|
void
|
|
|
|
|
xaccSchedXactionSetTemplateTrans(SchedXaction *sx, GList *t_t_list,
|
2003-06-25 00:52:46 +00:00
|
|
|
QofBook *book)
|
2001-08-30 06:24:55 +00:00
|
|
|
{
|
|
|
|
|
Transaction *new_trans;
|
|
|
|
|
TTInfo *tti;
|
|
|
|
|
TTSplitInfo *s_info;
|
|
|
|
|
Split *new_split;
|
|
|
|
|
GList *split_list;
|
2001-10-05 08:35:04 +00:00
|
|
|
|
2001-11-24 12:10:42 +00:00
|
|
|
g_return_if_fail (book);
|
2001-10-05 08:35:04 +00:00
|
|
|
|
|
|
|
|
/* delete any old transactions, if there are any */
|
2001-08-30 06:24:55 +00:00
|
|
|
delete_template_trans( sx );
|
|
|
|
|
|
|
|
|
|
for(;t_t_list != NULL; t_t_list = t_t_list->next)
|
|
|
|
|
{
|
|
|
|
|
tti = t_t_list->data;
|
|
|
|
|
|
2001-11-24 12:10:42 +00:00
|
|
|
new_trans = xaccMallocTransaction(book);
|
2001-08-30 06:24:55 +00:00
|
|
|
|
|
|
|
|
xaccTransBeginEdit(new_trans);
|
|
|
|
|
|
|
|
|
|
xaccTransSetDescription(new_trans,
|
|
|
|
|
gnc_ttinfo_get_description(tti));
|
|
|
|
|
|
|
|
|
|
xaccTransSetNum(new_trans,
|
|
|
|
|
gnc_ttinfo_get_num(tti));
|
2001-11-05 07:39:10 +00:00
|
|
|
xaccTransSetCurrency( new_trans,
|
|
|
|
|
gnc_ttinfo_get_currency(tti) );
|
2001-08-30 06:24:55 +00:00
|
|
|
|
|
|
|
|
for(split_list = gnc_ttinfo_get_template_splits(tti);
|
|
|
|
|
split_list;
|
|
|
|
|
split_list = split_list->next)
|
|
|
|
|
{
|
|
|
|
|
s_info = split_list->data;
|
2001-10-05 08:35:04 +00:00
|
|
|
new_split = pack_split_info(s_info, sx->template_acct,
|
2001-11-24 12:10:42 +00:00
|
|
|
new_trans, book);
|
2001-08-30 06:24:55 +00:00
|
|
|
xaccTransAppendSplit(new_trans, new_split);
|
|
|
|
|
}
|
|
|
|
|
xaccTransCommitEdit(new_trans);
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-10-22 09:17:34 +00:00
|
|
|
|
|
|
|
|
void*
|
2002-09-29 20:44:54 +00:00
|
|
|
gnc_sx_create_temporal_state( SchedXaction *sx )
|
2001-10-22 09:17:34 +00:00
|
|
|
{
|
2002-09-29 20:44:54 +00:00
|
|
|
temporalStateData *toRet =
|
|
|
|
|
g_new0( temporalStateData, 1 );
|
|
|
|
|
toRet->last_date = sx->last_date;
|
|
|
|
|
toRet->num_occur_rem = sx->num_occurances_remain;
|
|
|
|
|
toRet->num_inst = sx->instance_num;
|
|
|
|
|
return (void*)toRet;
|
2001-10-22 09:17:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2002-09-29 20:44:54 +00:00
|
|
|
gnc_sx_incr_temporal_state( SchedXaction *sx, void *stateData )
|
2001-10-22 09:17:34 +00:00
|
|
|
{
|
2002-09-29 20:44:54 +00:00
|
|
|
GDate unused;
|
2002-07-24 22:04:57 +00:00
|
|
|
temporalStateData *tsd = (temporalStateData*)stateData;
|
2002-09-29 20:44:54 +00:00
|
|
|
|
2002-10-06 22:31:05 +00:00
|
|
|
g_date_clear( &unused, 1 );
|
2002-09-29 20:44:54 +00:00
|
|
|
tsd->last_date =
|
|
|
|
|
xaccSchedXactionGetInstanceAfter( sx,
|
|
|
|
|
&unused,
|
|
|
|
|
stateData );
|
2002-04-16 07:09:16 +00:00
|
|
|
if ( xaccSchedXactionHasOccurDef( sx ) ) {
|
|
|
|
|
tsd->num_occur_rem -= 1;
|
|
|
|
|
}
|
2002-07-24 22:04:57 +00:00
|
|
|
tsd->num_inst += 1;
|
2001-10-22 09:17:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2002-09-29 20:44:54 +00:00
|
|
|
gnc_sx_revert_to_temporal_state( SchedXaction *sx, void *stateData )
|
2001-10-22 09:17:34 +00:00
|
|
|
{
|
2002-09-29 20:44:54 +00:00
|
|
|
temporalStateData *tsd = (temporalStateData*)stateData;
|
|
|
|
|
sx->last_date = tsd->last_date;
|
|
|
|
|
sx->num_occurances_remain = tsd->num_occur_rem;
|
|
|
|
|
sx->instance_num = tsd->num_inst;
|
|
|
|
|
sx->dirty = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
gnc_sx_destroy_temporal_state( void *stateData )
|
|
|
|
|
{
|
|
|
|
|
g_free( (temporalStateData*)stateData );
|
2002-04-16 07:09:16 +00:00
|
|
|
}
|
|
|
|
|
|
2002-07-01 19:12:37 +00:00
|
|
|
void*
|
2002-09-29 20:44:54 +00:00
|
|
|
gnc_sx_clone_temporal_state( void *stateData )
|
2002-04-16 07:09:16 +00:00
|
|
|
{
|
2002-09-29 20:44:54 +00:00
|
|
|
temporalStateData *toRet, *tsd;
|
|
|
|
|
tsd = (temporalStateData*)stateData;
|
|
|
|
|
toRet = g_memdup( tsd, sizeof( temporalStateData ) );
|
2002-04-16 07:09:16 +00:00
|
|
|
return (void*)toRet;
|
2001-10-22 09:17:34 +00:00
|
|
|
}
|
|
|
|
|
|
2002-09-29 20:44:54 +00:00
|
|
|
static
|
|
|
|
|
gint
|
|
|
|
|
_temporal_state_data_cmp( gconstpointer a, gconstpointer b )
|
|
|
|
|
{
|
|
|
|
|
temporalStateData *tsd_a, *tsd_b;
|
|
|
|
|
tsd_a = (temporalStateData*)a;
|
|
|
|
|
tsd_b = (temporalStateData*)b;
|
|
|
|
|
|
|
|
|
|
if ( !tsd_a && !tsd_b )
|
|
|
|
|
return 0;
|
|
|
|
|
if ( !tsd_a )
|
|
|
|
|
return 1;
|
|
|
|
|
if ( !tsd_b )
|
|
|
|
|
return -1;
|
|
|
|
|
return g_date_compare( &tsd_a->last_date,
|
|
|
|
|
&tsd_b->last_date );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds an instance to the deferred list of the SX. Added instances are
|
|
|
|
|
* added in (date-)sorted order.
|
|
|
|
|
**/
|
2002-04-16 07:09:16 +00:00
|
|
|
void
|
2002-09-29 20:44:54 +00:00
|
|
|
gnc_sx_add_defer_instance( SchedXaction *sx, void *deferStateData )
|
2002-04-16 07:09:16 +00:00
|
|
|
{
|
2002-09-29 20:44:54 +00:00
|
|
|
sx->deferredList = g_list_insert_sorted( sx->deferredList,
|
|
|
|
|
deferStateData,
|
|
|
|
|
_temporal_state_data_cmp );
|
2002-04-16 07:09:16 +00:00
|
|
|
}
|
|
|
|
|
|
2002-09-29 20:44:54 +00:00
|
|
|
/**
|
|
|
|
|
* Removes an instance from the deferred list. If the instance is no longer
|
|
|
|
|
* useful; gnc_sx_destroy_temporal_state() it.
|
|
|
|
|
**/
|
2002-04-16 07:09:16 +00:00
|
|
|
void
|
2002-09-29 20:44:54 +00:00
|
|
|
gnc_sx_remove_defer_instance( SchedXaction *sx, void *deferStateData )
|
2002-04-16 07:09:16 +00:00
|
|
|
{
|
2002-09-29 20:44:54 +00:00
|
|
|
sx->deferredList = g_list_remove( sx->deferredList, deferStateData );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the defer list from the SX; this is a (date-)sorted
|
|
|
|
|
* temporal-state-data instance list. The list should not be modified by the
|
|
|
|
|
* caller; use the gnc_sx_{add,remove}_defer_instance() functions to modifiy
|
|
|
|
|
* the list.
|
|
|
|
|
**/
|
|
|
|
|
GList*
|
|
|
|
|
gnc_sx_get_defer_instances( SchedXaction *sx )
|
|
|
|
|
{
|
|
|
|
|
return sx->deferredList;
|
2002-04-16 07:09:16 +00:00
|
|
|
}
|
2003-06-10 04:31:47 +00:00
|
|
|
|