mirror of
https://github.com/Gnucash/gnucash.git
synced 2026-10-12 17:32:00 -05:00
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@4907 57a11ea4-9604-0410-9ed3-97b8803252fd
768 lines
28 KiB
C
768 lines
28 KiB
C
/********************************************************************\
|
|
* dialog-sxsincelast.c - "since last run" dialog. *
|
|
* 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 <gnome.h>
|
|
#include <glib.h>
|
|
|
|
#include "gnc-engine-util.h"
|
|
#include "FileDialog.h"
|
|
#include "gnc-book.h"
|
|
#include "Transaction.h"
|
|
#include "Group.h"
|
|
#include "gnc-numeric.h"
|
|
#include "SchedXaction.h"
|
|
#include "gnc-component-manager.h"
|
|
#include "SplitLedger.h"
|
|
#include "gnc-ui-util.h"
|
|
#include "gnc-exp-parser.h"
|
|
#include "dialog-utils.h"
|
|
|
|
#include "dialog-sxsincelast.h"
|
|
|
|
#define DIALOG_SXSINCELAST_CM_CLASS "dialog-sxsincelast"
|
|
|
|
static short module = MOD_SX;
|
|
|
|
typedef struct _toCreateTransaction {
|
|
SchedXaction *sx;
|
|
GDate *date;
|
|
|
|
gint clistRow;
|
|
} toCreateTransaction;
|
|
|
|
typedef struct _sxSinceLastData {
|
|
GtkWidget *sxsincelastDlg;
|
|
GladeXML *gxml;
|
|
GList /* <toCreateTransaction*> */ *transList;
|
|
} sxSinceLastData;
|
|
|
|
typedef struct _reminderTuple {
|
|
GDate *endDate;
|
|
GDate *occurDate;
|
|
} reminderTuple;
|
|
|
|
static void sxsincelast_init( sxSinceLastData *sxsld );
|
|
static void sxsincelast_populate( sxSinceLastData *sxsld );
|
|
static void sxsincelast_close_handler( gpointer ud );
|
|
static void sxsincelast_ok_clicked( GtkButton *b, gpointer ud );
|
|
static void sxsincelast_cancel_clicked( GtkButton *b, gpointer ud );
|
|
|
|
static void sxsincelast_destroy( GtkObject *o, gpointer ud );
|
|
|
|
static void _create_transactions_on( SchedXaction *sx, GDate *gd );
|
|
|
|
static void processAutoCreateList( GList *, sxSinceLastData *sxsld, SchedXaction * );
|
|
static void processToCreateList( GList *, sxSinceLastData *sxsld, SchedXaction * );
|
|
static void processReminderList( GList *, sxSinceLastData *sxsld, SchedXaction * );
|
|
|
|
/* int parse_vars_from_formula( const char *formula, GHashTable *varHash ); */
|
|
|
|
void
|
|
gnc_ui_sxsincelast_guile_wrapper( char *foo )
|
|
{
|
|
gnc_ui_sxsincelast_dialog_create();
|
|
}
|
|
|
|
void
|
|
gnc_ui_sxsincelast_dialog_create(void)
|
|
{
|
|
sxSinceLastData *sxsld = g_new0( sxSinceLastData, 1 );
|
|
sxsld->gxml = gnc_glade_xml_new( "sched-xact.glade", "Real Since-Last-Run Dialog" );
|
|
sxsld->sxsincelastDlg = glade_xml_get_widget( sxsld->gxml, "Real Since-Last-Run Dialog" );
|
|
|
|
sxsincelast_init( sxsld );
|
|
}
|
|
|
|
static void
|
|
sxsincelast_init( sxSinceLastData *sxsld )
|
|
{
|
|
GtkWidget *o;
|
|
int i;
|
|
struct widgetSignalHandlerTuple {
|
|
char *name;
|
|
char *signal;
|
|
void (*handlerFn)();
|
|
} widgets[] = {
|
|
{ "ok_button", "clicked", sxsincelast_ok_clicked },
|
|
{ "cancel_button", "clicked", sxsincelast_cancel_clicked },
|
|
{ NULL, NULL, NULL }
|
|
};
|
|
|
|
gnc_register_gui_component( DIALOG_SXSINCELAST_CM_CLASS,
|
|
NULL,
|
|
sxsincelast_close_handler,
|
|
sxsld->sxsincelastDlg );
|
|
|
|
gtk_signal_connect( GTK_OBJECT(sxsld->sxsincelastDlg), "destroy",
|
|
GTK_SIGNAL_FUNC( sxsincelast_destroy ), sxsld );
|
|
|
|
for ( i=0; widgets[i].name != NULL ; i++ ) {
|
|
o = glade_xml_get_widget( sxsld->gxml, widgets[i].name );
|
|
gtk_signal_connect( GTK_OBJECT(o), widgets[i].signal,
|
|
GTK_SIGNAL_FUNC(widgets[i].handlerFn),
|
|
sxsld );
|
|
|
|
}
|
|
|
|
sxsincelast_populate( sxsld );
|
|
|
|
gtk_widget_show_all( sxsld->sxsincelastDlg );
|
|
}
|
|
|
|
static void
|
|
_generate_instances( SchedXaction *sx,
|
|
GDate *end,
|
|
GList **instanceList )
|
|
{
|
|
GDate gd, *gdToReturn;
|
|
char tmpBuf[26];
|
|
|
|
gd = xaccSchedXactionGetNextInstance( sx );
|
|
while ( g_date_valid(&gd)
|
|
&& g_date_compare( &gd, end ) <= 0 ) {
|
|
|
|
g_date_strftime( tmpBuf, 25, "%a, %b %e, %Y", &gd );
|
|
DEBUG( "Adding instance %s", tmpBuf );
|
|
|
|
gdToReturn = g_date_new();
|
|
*gdToReturn = gd;
|
|
*instanceList = g_list_append( *instanceList, gdToReturn );
|
|
|
|
gd = xaccSchedXactionGetInstanceAfter( sx, &gd );
|
|
}
|
|
if ( ! g_date_valid( &gd ) ) {
|
|
PERR( "Should be added to dead-list..." );
|
|
}
|
|
}
|
|
|
|
static void
|
|
_free_gdate_list_elts( gpointer data, gpointer user_data )
|
|
{
|
|
g_date_free( (GDate*)data );
|
|
}
|
|
|
|
static void
|
|
_free_reminderTuple_list_elts( gpointer data, gpointer user_data )
|
|
{
|
|
g_date_free( ((reminderTuple*)data)->occurDate );
|
|
g_free( (reminderTuple*)data );
|
|
}
|
|
|
|
static void
|
|
processAutoCreateList( GList *autoCreateList, sxSinceLastData *sxsld, SchedXaction *sx )
|
|
{
|
|
char tmpBuf[26];
|
|
int row;
|
|
GtkCList *cl;
|
|
gboolean autoCreateState, notifyState;
|
|
char *rowText[2];
|
|
|
|
row = 0;
|
|
|
|
/*
|
|
get the "automagically created and notification requested"
|
|
register, and create the entires.
|
|
For now, this is a clist...
|
|
*/
|
|
cl = GTK_CLIST( glade_xml_get_widget( sxsld->gxml, "auto_create_clist" ) );
|
|
gtk_clist_freeze( cl );
|
|
while ( autoCreateList ) {
|
|
g_date_strftime( tmpBuf, 25, "%a, %b %e, %Y",
|
|
(GDate*)autoCreateList->data );
|
|
xaccSchedXactionGetAutoCreate( sx, &autoCreateState, ¬ifyState );
|
|
|
|
_create_transactions_on( sx, (GDate*)autoCreateList->data );
|
|
|
|
if ( notifyState ) {
|
|
rowText[0] = xaccSchedXactionGetName( sx );
|
|
rowText[1] = malloc( sizeof(gchar) * 26 ); /* FIXME */
|
|
g_date_strftime( rowText[1], 25, "%a, %b %e, %Y",
|
|
(GDate*)autoCreateList->data );
|
|
gtk_clist_insert( cl, row++, rowText );
|
|
}
|
|
|
|
autoCreateList = autoCreateList->next;
|
|
}
|
|
gtk_clist_thaw( cl );
|
|
|
|
}
|
|
|
|
static void
|
|
processToCreateList( GList *toCreateList, sxSinceLastData *sxsld, SchedXaction *sx )
|
|
{
|
|
GtkCList *clist;
|
|
int row;
|
|
char *rowText[2];
|
|
|
|
row = 0;
|
|
if ( toCreateList == NULL )
|
|
return;
|
|
|
|
clist = GTK_CLIST( glade_xml_get_widget( sxsld->gxml, "to_create_clist" ) );
|
|
do {
|
|
/* add to clist [ahem... register... ahem] */
|
|
rowText[0] = xaccSchedXactionGetName( sx );
|
|
rowText[1] = malloc( sizeof(char) * 25 ); /* FIXME */
|
|
g_date_strftime( rowText[1], 25, "%a, %b %e, %Y", (GDate*)toCreateList->data );
|
|
gtk_clist_insert( clist, row++, rowText );
|
|
} while ( (toCreateList = toCreateList->next) );
|
|
}
|
|
|
|
static void
|
|
processReminderList( GList *reminderList, sxSinceLastData *sxsld, SchedXaction *sx )
|
|
{
|
|
GtkCList *clist;
|
|
int row;
|
|
char *rowText[3];
|
|
reminderTuple *rt;
|
|
|
|
/* . need
|
|
. orig end date
|
|
. this instance date
|
|
. sx
|
|
*/
|
|
|
|
row = 0;
|
|
|
|
if ( reminderList == NULL )
|
|
return;
|
|
|
|
clist = GTK_CLIST( glade_xml_get_widget( sxsld->gxml, "reminders_clist" ) );
|
|
|
|
do {
|
|
rt = (reminderTuple*)reminderList->data;
|
|
/* add to clist [ahem... register... ahem] */
|
|
rowText[0] = xaccSchedXactionGetName( sx );
|
|
rowText[1] = malloc( sizeof(gchar) * 25 ); /* FIXME */
|
|
g_date_strftime( rowText[1], 25, "%a, %b %e, %Y", rt->occurDate );
|
|
rowText[2] = malloc( sizeof(gchar) * 5 ); /* FIXME */
|
|
sprintf( rowText[2], "%d",
|
|
(g_date_julian(rt->occurDate) - g_date_julian(rt->endDate)) );
|
|
|
|
gtk_clist_insert( clist, row++, rowText );
|
|
} while ( (reminderList = reminderList->next) );
|
|
}
|
|
|
|
|
|
static void
|
|
sxsincelast_populate( sxSinceLastData *sxsld )
|
|
{
|
|
|
|
GList *sxList, *instanceList;
|
|
GList *autoCreateList, *toCreateList, *reminderList;
|
|
SchedXaction *sx;
|
|
GDate end, endPlusReminders;
|
|
GDate *instDate;
|
|
gint daysInAdvance;
|
|
gboolean autocreateState, notifyState;
|
|
gchar *rowText[3];
|
|
GtkWidget *w;
|
|
gint autoCreateRow, toCreateRow, remindersRow;
|
|
reminderTuple *rt;
|
|
|
|
autoCreateList = toCreateList = reminderList = NULL;
|
|
autoCreateRow = toCreateRow = remindersRow = 0;
|
|
|
|
sxList = gnc_book_get_schedxactions( gncGetCurrentBook() );
|
|
|
|
if ( sxList == NULL ) {
|
|
DEBUG( "No scheduled transactions to populate." );
|
|
return;
|
|
}
|
|
|
|
do {
|
|
sx = (SchedXaction*)sxList->data;
|
|
g_date_set_time( &end, time(NULL) );
|
|
daysInAdvance = xaccSchedXactionGetAdvanceCreation( sx );
|
|
g_date_add_days( &end, daysInAdvance );
|
|
|
|
endPlusReminders = end;
|
|
daysInAdvance = xaccSchedXactionGetAdvanceReminder( sx );
|
|
g_date_add_days( &endPlusReminders, daysInAdvance );
|
|
|
|
|
|
if (0) {
|
|
char tmpBuf[26];
|
|
|
|
g_date_strftime( tmpBuf, 25, "%a, %b %e, %Y", &end );
|
|
DEBUG( "We'll generate the appropriate instances, now for "
|
|
"SX \"%s\" with end time %s...",
|
|
xaccSchedXactionGetName(sx),
|
|
tmpBuf );
|
|
}
|
|
instanceList = NULL;
|
|
_generate_instances( sx, &endPlusReminders, &instanceList );
|
|
|
|
if ( instanceList == NULL )
|
|
continue;
|
|
|
|
xaccSchedXactionGetAutoCreate( sx, &autocreateState, ¬ifyState );
|
|
do {
|
|
instDate = (GDate*)instanceList->data;
|
|
if ( 0 ) {
|
|
char tmpBuf[26];
|
|
g_date_strftime( tmpBuf, 25, "%a, %b %e, %Y", instDate );
|
|
DEBUG( "SX \"%s\" instance on %s",
|
|
xaccSchedXactionGetName(sx), tmpBuf );
|
|
}
|
|
|
|
if ( (g_date_compare( &end, &endPlusReminders ) != 0)
|
|
&& (g_date_compare( &end, instDate ) <= 0) ) {
|
|
/* DEBUG( "\tIs a reminder" ); */
|
|
rt = g_new0( reminderTuple, 1 );
|
|
rt->endDate = &end;
|
|
rt->occurDate = instDate;
|
|
reminderList = g_list_append( reminderList, rt );
|
|
} else {
|
|
if ( autocreateState ) {
|
|
/* DEBUG( "\tauto-create" ); */
|
|
autoCreateList = g_list_append( autoCreateList,
|
|
instDate );
|
|
} else {
|
|
/* DEBUG( "\tAdding to create list" ); */
|
|
toCreateList = g_list_append( toCreateList,
|
|
instDate );
|
|
}
|
|
}
|
|
} while ( (instanceList = instanceList->next) );
|
|
|
|
/* process the lists */
|
|
processAutoCreateList( autoCreateList, sxsld, sx );
|
|
processToCreateList ( toCreateList, sxsld, sx );
|
|
processReminderList ( reminderList, sxsld, sx );
|
|
|
|
g_list_foreach( autoCreateList, _free_gdate_list_elts, NULL );
|
|
g_list_free( autoCreateList );
|
|
|
|
g_list_foreach( reminderList, _free_reminderTuple_list_elts, NULL );
|
|
g_list_free( reminderList );
|
|
|
|
/* FIXME: freeup the toCreate list at a more appropriate
|
|
time. */
|
|
|
|
} while ( (sxList = sxList->next) );
|
|
}
|
|
|
|
static void
|
|
sxsincelast_close_handler( gpointer ud )
|
|
{
|
|
gnome_dialog_close( GNOME_DIALOG( ((sxSinceLastData*)ud)->sxsincelastDlg ) );
|
|
}
|
|
|
|
static void
|
|
free_elts( gpointer data, gpointer user_data )
|
|
{
|
|
g_free( data );
|
|
}
|
|
|
|
static void
|
|
sxsincelast_ok_clicked( GtkButton *b, gpointer ud )
|
|
{
|
|
sxSinceLastData *sxsld;
|
|
GtkWidget *dlg;
|
|
GtkWidget *o;
|
|
GtkCList *cl;
|
|
time_t gdeDate;
|
|
GList *sxList;
|
|
GNCBook *book;
|
|
SchedXaction *sx;
|
|
GDate gd, *endDate;
|
|
gchar buf[1024];
|
|
gint row;
|
|
char *rowText[2];
|
|
toCreateTransaction *tct;
|
|
|
|
|
|
sxsld = (sxSinceLastData*)ud;
|
|
|
|
sxsincelast_close_handler( sxsld );
|
|
/* FIXME: the SX/date list already has been generated; we should use that. */
|
|
#if 0
|
|
o = glade_xml_get_widget( sxsld->gxml, "next_date" );
|
|
gdeDate = gnome_date_edit_get_date( GNOME_DATE_EDIT(o) );
|
|
|
|
DEBUG( "Okay... I should run with a date of: %s", ctime(&gdeDate) );
|
|
|
|
/* destroy the previous transactions
|
|
destroy all the toCreateTransactions */
|
|
if ( sxsld->transList != NULL ) {
|
|
g_list_foreach( sxsld->transList, free_elts, NULL );
|
|
g_list_free( sxsld->transList );
|
|
sxsld->transList = NULL;
|
|
}
|
|
|
|
book = gncGetCurrentBook();
|
|
sxList = gnc_book_get_schedxactions( book );
|
|
if ( sxList == NULL ) {
|
|
PERR( "No scheduled transactions to play with\n" );
|
|
return;
|
|
}
|
|
|
|
endDate = g_date_new();
|
|
g_date_set_time( endDate, gdeDate );
|
|
|
|
o = glade_xml_get_widget( sxsld->gxml, "replace_with_register" );
|
|
cl = GTK_CLIST(o);
|
|
gtk_clist_clear( cl );
|
|
|
|
g_date_clear( &gd, 1 );
|
|
row = 0;
|
|
do {
|
|
sx = (SchedXaction*)sxList->data;
|
|
// this is really "last-run-date", right?
|
|
g_date_set_time( &gd, time(NULL) );
|
|
|
|
gd = xaccSchedXactionGetInstanceAfter( sx, &gd );
|
|
while ( g_date_compare( &gd, endDate ) <= 0
|
|
&& g_date_valid( &gd ) ) {
|
|
|
|
g_date_strftime( buf, 1023, "%a, %b %e, %Y", &gd );
|
|
/* add to clist [ahem... register... ahem] */
|
|
rowText[0] = xaccSchedXactionGetName( sx );
|
|
rowText[1] = malloc( sizeof(char) * 256 ); /* FIXME */
|
|
g_date_strftime( rowText[1], 255, "%a, %b %e, %Y", &gd );
|
|
|
|
tct = g_new0( toCreateTransaction, 1 );
|
|
tct->sx = sx;
|
|
tct->date = g_date_new();
|
|
*tct->date = gd;
|
|
tct->clistRow = row;
|
|
sxsld->transList = g_list_append( sxsld->transList, tct );
|
|
|
|
gtk_clist_insert( cl, row, rowText );
|
|
row += 1;
|
|
gd = xaccSchedXactionGetInstanceAfter( sx, &gd );
|
|
}
|
|
} while ( (sxList = sxList->next) );
|
|
|
|
g_date_free( endDate );
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
sxsincelast_cancel_clicked( GtkButton *o, gpointer ud )
|
|
{
|
|
sxsincelast_close_handler( ud );
|
|
}
|
|
|
|
static void
|
|
sxsincelast_destroy( GtkObject *o, gpointer ud )
|
|
{
|
|
DEBUG( "nuttin' doin...\n" );
|
|
}
|
|
|
|
static gboolean
|
|
_create_each_transaction( Transaction *t, void *d )
|
|
{
|
|
Transaction *newT;
|
|
GDate *gd;
|
|
GList *sList;
|
|
GList *osList;
|
|
Split *split;
|
|
kvp_frame *split_kvpf;
|
|
kvp_value *kvp_val;
|
|
gboolean errFlag;
|
|
|
|
errFlag = FALSE;
|
|
|
|
DEBUG( "I'm seeing Transaction \"%s\"",
|
|
xaccTransGetDescription( t ) );
|
|
|
|
gd = (GDate*)d;
|
|
|
|
newT = xaccMallocTransaction();
|
|
xaccTransBeginEdit( newT );
|
|
/* the action and description/memo are in the template */
|
|
gnc_copy_trans_onto_trans( t, newT, FALSE, FALSE );
|
|
|
|
/* the date is new [gd] */
|
|
xaccTransSetDate( newT,
|
|
g_date_day( gd ),
|
|
g_date_month( gd ),
|
|
g_date_year( gd ) );
|
|
|
|
/* the accounts and amounts are in the kvp_frames of the splits. */
|
|
osList = xaccTransGetSplitList( t );
|
|
sList = xaccTransGetSplitList( newT );
|
|
if ( (osList == NULL) || (sList == NULL) ) {
|
|
PERR( "\tseen transaction w/o splits. :(" );
|
|
return FALSE;
|
|
}
|
|
do {
|
|
split = (Split*)sList->data;
|
|
/* FIXME: Ick. This assumes that the split lists will be
|
|
ordered identically. :( I think it's fair to say they
|
|
will, but I'd rather not have to count on it. --jsled */
|
|
split_kvpf = xaccSplitGetSlots( (Split*)osList->data );
|
|
|
|
DEBUG( "\tProcessing Split \"%s\"",
|
|
xaccSplitGetMemo( split ) );
|
|
|
|
DEBUG( "\tkvp_frame: %s\n",
|
|
kvp_frame_to_string( split_kvpf ) );
|
|
|
|
|
|
/* from-transaction of splits */
|
|
{
|
|
GUID *acct_guid;
|
|
Account *acct;
|
|
/* contains the guid of the split's actual account. */
|
|
kvp_val = kvp_frame_get_slot( split_kvpf, "sched-xaction/xfrm" );
|
|
if ( kvp_val == NULL ) {
|
|
PERR( "Null kvp_val for xfrm" );
|
|
}
|
|
acct_guid = kvp_value_get_guid( kvp_val );
|
|
acct = xaccAccountLookup( acct_guid );
|
|
DEBUG( "Got account with name \"%s\"",
|
|
xaccAccountGetName( acct ) );
|
|
/* xaccSplitSetAccount( split, acct ); */
|
|
xaccAccountInsertSplit( acct, split );
|
|
}
|
|
/* credit/debit formulas */
|
|
{
|
|
char *str;
|
|
gnc_numeric credit_num;
|
|
gnc_numeric debit_num;
|
|
gnc_numeric final;
|
|
int gncn_error;
|
|
|
|
kvp_val = kvp_frame_get_slot( split_kvpf, "sched-xaction/credit_formula" );
|
|
str = kvp_value_get_string( kvp_val );
|
|
credit_num = gnc_numeric_create( 0, 1 );
|
|
if ( str != NULL ) {
|
|
/* parse_vars_from_formula( str, NULL ); */
|
|
|
|
xaccParseAmount( str, TRUE, &credit_num, NULL );
|
|
/* string_to_gnc_numeric( str, &credit_num ); */
|
|
DEBUG( "gnc_numeric::credit: \"%s\" -> \"%s\"",
|
|
str, gnc_numeric_to_string( credit_num ) );
|
|
}
|
|
|
|
kvp_val = kvp_frame_get_slot( split_kvpf, "sched-xaction/debit_formula" );
|
|
str = kvp_value_get_string( kvp_val );
|
|
|
|
debit_num = gnc_numeric_create( 0, 1 );
|
|
if ( str != NULL ) {
|
|
/* parse_vars_from_formula( str, NULL ); */
|
|
|
|
xaccParseAmount( str, TRUE, &debit_num, NULL );
|
|
/* string_to_gnc_numeric( str, &debit_num ); */
|
|
DEBUG( "gnc_numeric::debit: \"%s\" -> \"%s\"",
|
|
str, gnc_numeric_to_string( debit_num ) );
|
|
}
|
|
|
|
final = gnc_numeric_sub_fixed( credit_num, debit_num );
|
|
|
|
gncn_error = gnc_numeric_check( final );
|
|
if ( gncn_error != GNC_ERROR_OK ) {
|
|
PERR( "Error %d in final gnc_numeric value", gncn_error );
|
|
errFlag = TRUE;
|
|
break;
|
|
}
|
|
DEBUG( "gnc_numeric::final: \"%s\"",
|
|
gnc_numeric_to_string( final ) );
|
|
xaccSplitSetValue( split, final );
|
|
}
|
|
#if 0
|
|
kvp_val = kvp_frame_get_slot( split_kvpf, "sched-xaction/shares" );
|
|
kvp_val = kvp_frame_get_slot( split_kvpf, "sched-xaction/amnt" );
|
|
#endif /* 0 */
|
|
} while ( (sList = sList->next) && (osList = osList->next) );
|
|
|
|
if ( errFlag ) {
|
|
PERR( "Some error in new transaction creation..." );
|
|
xaccTransRollbackEdit( newT );
|
|
} else {
|
|
xaccTransCommitEdit( newT );
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
static void
|
|
_create_transactions_on( SchedXaction *sx, GDate *gd )
|
|
{
|
|
AccountGroup *ag;
|
|
Account *acct;
|
|
char *id;
|
|
char tmpBuf[26];
|
|
|
|
{
|
|
g_date_strftime( tmpBuf, 25, "%a, %b %e, %Y", gd );
|
|
DEBUG( "Creating transactions on %s for %s",
|
|
tmpBuf, xaccSchedXactionGetName( sx ) );
|
|
}
|
|
|
|
ag = gnc_book_get_template_group( gncGetCurrentBook() );
|
|
id = guid_to_string( xaccSchedXactionGetGUID(sx) );
|
|
acct = xaccGetAccountFromName( ag, id );
|
|
DEBUG( "Got account \"%s\"\n",
|
|
xaccAccountGetName( acct ) );
|
|
g_free( id );
|
|
|
|
xaccAccountForEachTransaction( acct,
|
|
_create_each_transaction,
|
|
gd );
|
|
xaccSchedXactionSetLastOccurDate( sx, gd );
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
/**
|
|
* Parses in-fix mathematical formulas using the standard operators
|
|
* [+-/%*], and '(', ')' grouping.
|
|
*
|
|
* Any strings are placed in the GHashTable as variables. The value of
|
|
* each key in the hash-table is a struct of the form:
|
|
* { const char *varStr;
|
|
* gint idx;
|
|
* gint len; };
|
|
*
|
|
**/
|
|
int
|
|
parse_vars_from_formula( const char *formula, GHashTable *varHash )
|
|
{
|
|
gnc_numeric num_foo;
|
|
char *foo;
|
|
GList *list;
|
|
|
|
gnc_exp_parser_init();
|
|
if ( ! gnc_exp_parser_parse( formula, &num_foo, &foo ) ) {
|
|
PERR( "Error parsing at \"%s\": %s\n",
|
|
foo, gnc_exp_parser_error_string() );
|
|
}
|
|
PINFO( "Successful parse...\n" );
|
|
list = gnc_exp_parser_get_variable_names();
|
|
if ( list == NULL ) {
|
|
PINFO( "NULL variable list\n" );
|
|
} else {
|
|
do {
|
|
PINFO( "Variable \"%s\"\n",
|
|
list->data );
|
|
} while ( (list = list->next) );
|
|
}
|
|
|
|
gnc_exp_parser_shutdown();
|
|
}
|
|
#endif /* 0 */
|
|
|
|
#if 0
|
|
GScanner *varScanner;
|
|
GTokenType tok;
|
|
|
|
varScanner = g_scanner_new( NULL );
|
|
g_scanner_set_scope( varScanner, 0 );
|
|
g_scanner_freeze_symbol_table( varScanner );
|
|
g_scanner_scope_add_symbol( varScanner, 0, "(", (gpointer)"left-paren" );
|
|
g_scanner_scope_add_symbol( varScanner, 0, ")", (gpointer)"right-paren" );
|
|
g_scanner_scope_add_symbol( varScanner, 0, "+", (gpointer)"plus" );
|
|
g_scanner_scope_add_symbol( varScanner, 0, "-", (gpointer)"minus" );
|
|
g_scanner_scope_add_symbol( varScanner, 0, "/", (gpointer)"div" );
|
|
g_scanner_scope_add_symbol( varScanner, 0, "*", (gpointer)"mult" );
|
|
g_scanner_thaw_symbol_table( varScanner );
|
|
|
|
g_scanner_input_text( varScanner, formula, strlen( formula ) );
|
|
|
|
do {
|
|
tok = g_scanner_get_next_token( varScanner );
|
|
printf( "tok: " );
|
|
switch ( varScanner->token ) {
|
|
case G_TOKEN_EOF:
|
|
printf( "EOF" ); break;
|
|
case G_TOKEN_LEFT_PAREN:
|
|
printf( "(" ); break;
|
|
case G_TOKEN_RIGHT_PAREN:
|
|
printf( ")" ); break;
|
|
case G_TOKEN_LEFT_CURLY:
|
|
printf( "{" ); break;
|
|
case G_TOKEN_RIGHT_CURLY:
|
|
printf( "}" ); break;
|
|
case G_TOKEN_LEFT_BRACE:
|
|
printf( "[" ); break;
|
|
case G_TOKEN_RIGHT_BRACE:
|
|
printf( "]" ); break;
|
|
case G_TOKEN_EQUAL_SIGN:
|
|
printf( "=" ); break;
|
|
case G_TOKEN_COMMA:
|
|
printf( "," ); break;
|
|
case G_TOKEN_NONE:
|
|
printf( "NONE" ); break;
|
|
case G_TOKEN_ERROR:
|
|
printf( "ERROR(%d)", varScanner->value.v_error ); break;
|
|
case G_TOKEN_CHAR:
|
|
printf( "CHAR(%c)", varScanner->value.v_char ); break;
|
|
case G_TOKEN_BINARY:
|
|
printf( "BINARY" ); break;
|
|
case G_TOKEN_OCTAL:
|
|
printf( "OCTAL(%ul)", varScanner->value.v_octal ); break;
|
|
case G_TOKEN_INT:
|
|
printf( "INT(%ul)", varScanner->value.v_int ); break;
|
|
case G_TOKEN_HEX:
|
|
printf( "HEX(%ul)", varScanner->value.v_hex ); break;
|
|
case G_TOKEN_FLOAT:
|
|
printf( "FLOAT(%f)", varScanner->value.v_float ); break;
|
|
case G_TOKEN_STRING:
|
|
printf( "STRING(%s)", varScanner->value.v_string ); break;
|
|
case G_TOKEN_SYMBOL:
|
|
printf( "SYMBOL(%s)", (gchar*)varScanner->value.v_symbol ); break;
|
|
case G_TOKEN_IDENTIFIER:
|
|
printf( "IDENT(%s)", varScanner->value.v_identifier ); break;
|
|
case G_TOKEN_IDENTIFIER_NULL:
|
|
printf( "NULL_IDENT" ); break;
|
|
case G_TOKEN_COMMENT_SINGLE:
|
|
case G_TOKEN_COMMENT_MULTI:
|
|
printf( "COMMENT(%s)", varScanner->value.v_comment ); break;
|
|
case G_TOKEN_LAST:
|
|
printf( "END" ); break;
|
|
default:
|
|
printf( "UNK" ); break;
|
|
};
|
|
printf( "\n" );
|
|
} while ( (varScanner->token != G_TOKEN_LAST) &&
|
|
(varScanner->token != G_TOKEN_EOF) &&
|
|
(varScanner->token != G_TOKEN_NONE) );
|
|
return 1;
|
|
/*
|
|
"0.33 * ( base + ld ) + (0.25 * internet)":
|
|
|
|
tok: FLOAT(0.330000)
|
|
tok: UNK
|
|
tok: )
|
|
tok: IDENT(base)
|
|
tok: UNK
|
|
tok: IDENT(ld)
|
|
tok: (
|
|
tok: UNK
|
|
tok: )
|
|
tok: FLOAT(0.250000)
|
|
tok: UNK
|
|
tok: IDENT(internet)
|
|
tok: (
|
|
tok: EOF
|
|
*/
|
|
|
|
#endif /* 0 */
|