mirror of https://github.com/Gnucash/gnucash
* src/gnome/gnc-schedxaction-xml-v2.c: Support for new
SchedXaction options [create/remind-days-in-advance; auto-create,
notify-on-creation].
* src/gnome/dialog-scheduledxaction.c (putSchedXactionInClist):
Fix for next-occurance processing.
* src/engine/SchedXaction.c (xaccSchedXactionGetNextInstance):
Better handling of start date/last-occur date/current dates when
generating the next occurance date. Gotta remember to clear those
g_dates, lest the come up 'valid' due to stack trash... :(
* src/gnome/gnc-sxlastrun.{h,c}: Added; newer/better
since-last-occur dialog.
* src/gnome/window-main.c: Added Scheduled Transaction stuff to
"Tools" menu.
* src/scm/prefs.scm: Added initial cut at Scheduled Transaction
preferences.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@4905 57a11ea4-9604-0410-9ed3-97b8803252fd
zzzoldfeatures/g2-gog-integ
parent
890be8ccfc
commit
d82bd05dfc
@ -0,0 +1,766 @@
|
||||
/********************************************************************\
|
||||
* 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." );
|
||||
}
|
||||
|
||||
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 */
|
||||
@ -0,0 +1,29 @@
|
||||
/********************************************************************\
|
||||
* dialog-sxsincelast.h - SchedXaction "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 *
|
||||
\********************************************************************/
|
||||
|
||||
#ifndef DIALOG_SXSINCELAST_H
|
||||
#define DIALOG_SXSINCELAST_H
|
||||
|
||||
void gnc_ui_sxsincelast_dialog_create( void );
|
||||
void gnc_ui_sxsincelast_guile_wrapper( char* );
|
||||
|
||||
#endif // !defined(DIALOG_SXSINCELAST_H)
|
||||
Loading…
Reference in new issue