mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Start the FreqSpec->Recurrence migration:
- remove the "private" SX header. - add GList<Recurrence*> to the SX model - Parse a GList<Recurrence> from FreqSpec xml. - GncFrequency changes - modify GncFrequency to load/save Recurrences. - simplify GncFrequency: remove "daily [m-f]", "bi-weekly" and super-monthly pages. - add (Recurrence-only) support for "last weekday of month" to {,semi-}monthly - update SX cleanup todo-list. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@15601 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
d02ccef535
commit
1d2e90dce7
@ -125,6 +125,9 @@ typedef struct
|
||||
FreqSpec *fs; /* FreqSpec we're parsing into. */
|
||||
QofBook *book; /* Book we're loading into. */
|
||||
|
||||
Recurrence *recurrence;
|
||||
GList *recurrence_list;
|
||||
|
||||
/* fields used in the union of unions... :) */
|
||||
GDate once_day; /* once */
|
||||
gint64 interval; /* all [except once] */
|
||||
@ -140,6 +143,8 @@ fspd_init( fsParseData *fspd )
|
||||
fspd->fs = NULL;
|
||||
fspd->list = NULL;
|
||||
fspd->book = NULL;
|
||||
fspd->recurrence = g_new0(Recurrence, 1);
|
||||
fspd->recurrence_list = NULL;
|
||||
fspd->interval
|
||||
= fspd->offset
|
||||
= fspd->day
|
||||
@ -399,10 +404,24 @@ fs_subelement_handler( xmlNodePtr node, gpointer data )
|
||||
{
|
||||
fsParseData *fspd = data;
|
||||
FreqSpec *fs;
|
||||
GList *recurrences;
|
||||
|
||||
fs = dom_tree_to_freqSpec( node, fspd->book );
|
||||
if ( fs == NULL )
|
||||
return FALSE;
|
||||
fspd->list = g_list_append( fspd->list, fs );
|
||||
|
||||
recurrences = dom_tree_freqSpec_to_recurrences(node, fspd->book);
|
||||
if (recurrences == NULL)
|
||||
return FALSE;
|
||||
|
||||
{
|
||||
GList *r_iter;
|
||||
for (r_iter = recurrences; r_iter != NULL; r_iter = r_iter->next)
|
||||
{
|
||||
fspd->recurrence_list = g_list_append(fspd->recurrence_list, r_iter->data);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -417,8 +436,15 @@ struct dom_tree_handler fs_union_dom_handlers[] = {
|
||||
{ NULL, NULL, 0, 0 },
|
||||
};
|
||||
|
||||
static
|
||||
gboolean
|
||||
static void
|
||||
compute_date(fsParseData *parsed, GDate *date)
|
||||
{
|
||||
g_date_clear(date, 1);
|
||||
g_date_set_dmy(date, 1, 1, 1970);
|
||||
g_date_add_days(date, parsed->offset);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fs_none_handler( xmlNodePtr node, gpointer data )
|
||||
{
|
||||
fsParseData *fspd = data;
|
||||
@ -444,22 +470,27 @@ fs_once_handler( xmlNodePtr node, gpointer data )
|
||||
fspd );
|
||||
if ( !successful )
|
||||
return FALSE;
|
||||
recurrenceSet(fspd->recurrence, 0, PERIOD_ONCE, &fspd->once_day);
|
||||
|
||||
|
||||
fspd->fs->type = ONCE;
|
||||
fspd->fs->s.once.date = fspd->once_day;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
fs_daily_handler( xmlNodePtr node, gpointer data)
|
||||
static gboolean
|
||||
fs_daily_handler(xmlNodePtr node, gpointer data)
|
||||
{
|
||||
fsParseData *fspd = data;
|
||||
GDate offset_date;
|
||||
gboolean successful;
|
||||
successful = dom_tree_generic_parse( node,
|
||||
fs_union_dom_handlers,
|
||||
fspd );
|
||||
if ( !successful )
|
||||
return FALSE;
|
||||
successful = dom_tree_generic_parse(node, fs_union_dom_handlers, fspd );
|
||||
if (!successful)
|
||||
return FALSE;
|
||||
|
||||
compute_date(fspd, &offset_date);
|
||||
recurrenceSet(fspd->recurrence, fspd->interval, PERIOD_DAY, &offset_date);
|
||||
|
||||
fspd->fs->type = DAILY;
|
||||
fspd->fs->s.daily.interval_days = fspd->interval;
|
||||
fspd->fs->s.daily.offset_from_epoch = fspd->offset;
|
||||
@ -471,15 +502,21 @@ gboolean
|
||||
fs_weekly_handler( xmlNodePtr node, gpointer data )
|
||||
{
|
||||
fsParseData *fspd = data;
|
||||
GDate offset_date;
|
||||
gboolean successful;
|
||||
successful = dom_tree_generic_parse( node,
|
||||
fs_union_dom_handlers,
|
||||
fspd );
|
||||
if ( !successful )
|
||||
return FALSE;
|
||||
|
||||
compute_date(fspd, &offset_date);
|
||||
recurrenceSet(fspd->recurrence, fspd->interval, PERIOD_DAY, &offset_date);
|
||||
|
||||
fspd->fs->type = WEEKLY;
|
||||
fspd->fs->s.weekly.interval_weeks = fspd->interval;
|
||||
fspd->fs->s.weekly.offset_from_epoch = fspd->offset;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -488,16 +525,23 @@ gboolean
|
||||
fs_monthly_handler( xmlNodePtr node, gpointer data)
|
||||
{
|
||||
fsParseData *fspd = data;
|
||||
GDate offset_date;
|
||||
gboolean successful;
|
||||
successful = dom_tree_generic_parse( node,
|
||||
fs_union_dom_handlers,
|
||||
fspd );
|
||||
if ( !successful )
|
||||
return FALSE;
|
||||
compute_date(fspd, &offset_date);
|
||||
|
||||
g_date_set_day(&offset_date, fspd->day);
|
||||
recurrenceSet(fspd->recurrence, fspd->interval, PERIOD_MONTH, &offset_date);
|
||||
|
||||
fspd->fs->type = MONTHLY;
|
||||
fspd->fs->s.monthly.interval_months = fspd->interval;
|
||||
fspd->fs->s.monthly.offset_from_epoch = fspd->offset;
|
||||
fspd->fs->s.monthly.day_of_month = fspd->day;
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
@ -505,19 +549,8 @@ static
|
||||
gboolean
|
||||
fs_month_relative_handler( xmlNodePtr node, gpointer data)
|
||||
{
|
||||
fsParseData *fspd = data;
|
||||
gboolean successful;
|
||||
successful = dom_tree_generic_parse( node,
|
||||
fs_union_dom_handlers,
|
||||
fspd );
|
||||
if ( !successful )
|
||||
return FALSE;
|
||||
fspd->fs->type = MONTH_RELATIVE;
|
||||
fspd->fs->s.month_relative.interval_months = fspd->interval;
|
||||
fspd->fs->s.month_relative.offset_from_epoch = fspd->offset;
|
||||
fspd->fs->s.month_relative.weekday = fspd->day;
|
||||
fspd->fs->s.month_relative.occurrence = fspd->occurrence;
|
||||
return TRUE;
|
||||
g_critical("this was never supported, how is it in the datafile?");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
@ -544,6 +577,7 @@ fs_composite_handler( xmlNodePtr node, gpointer data)
|
||||
return FALSE;
|
||||
fspd->fs->type = COMPOSITE;
|
||||
fspd->fs->s.composites.subSpecs = fspd->list;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -604,21 +638,40 @@ gnc_freqSpec_sixtp_parser_create(void)
|
||||
return sixtp_dom_parser_new( gnc_freqSpec_end_handler, NULL, NULL );
|
||||
}
|
||||
|
||||
static void
|
||||
common_parse(fsParseData *fspd, xmlNodePtr node, QofBook *book)
|
||||
{
|
||||
gboolean successful;
|
||||
|
||||
fspd->book = book;
|
||||
fspd->fs = xaccFreqSpecMalloc(book);
|
||||
successful = dom_tree_generic_parse( node, fs_dom_handlers, fspd );
|
||||
if (!successful)
|
||||
{
|
||||
xmlElemDump(stdout, NULL, node);
|
||||
xaccFreqSpecFree( fspd->fs );
|
||||
fspd->fs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GList*
|
||||
dom_tree_freqSpec_to_recurrences(xmlNodePtr node, QofBook *book)
|
||||
{
|
||||
fsParseData fspd;
|
||||
fspd_init( &fspd );
|
||||
common_parse(&fspd, node, book);
|
||||
if (fspd.recurrence_list == NULL)
|
||||
{
|
||||
fspd.recurrence_list = g_list_append(fspd.recurrence_list, fspd.recurrence);
|
||||
}
|
||||
return fspd.recurrence_list;
|
||||
}
|
||||
|
||||
FreqSpec*
|
||||
dom_tree_to_freqSpec(xmlNodePtr node, QofBook *book)
|
||||
{
|
||||
gboolean successful;
|
||||
fsParseData fspd;
|
||||
|
||||
fspd_init( &fspd );
|
||||
fspd.book = book;
|
||||
|
||||
fspd.fs = xaccFreqSpecMalloc(book);
|
||||
successful = dom_tree_generic_parse( node, fs_dom_handlers, &fspd );
|
||||
if ( !successful ) {
|
||||
xmlElemDump(stdout, NULL, node);
|
||||
xaccFreqSpecFree( fspd.fs );
|
||||
fspd.fs = NULL;
|
||||
}
|
||||
common_parse(&fspd, node, book);
|
||||
return fspd.fs;
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ static struct dom_tree_handler recurrence_dom_handlers[] = {
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
Recurrence *
|
||||
Recurrence*
|
||||
dom_tree_to_recurrence(xmlNodePtr node)
|
||||
{
|
||||
gboolean successful;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/********************************************************************
|
||||
* gnc-schedxactions-xml-v2.c -- xml routines for transactions *
|
||||
* Copyright (C) 2001 Joshua Sled <jsled@asynchronous.org> *
|
||||
* Copyright (C) 2001,2007 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 *
|
||||
@ -27,7 +27,6 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "Group.h"
|
||||
#include "SchedXactionP.h"
|
||||
#include "SX-book.h"
|
||||
|
||||
#include "gnc-xml-helper.h"
|
||||
@ -46,7 +45,10 @@
|
||||
|
||||
#include "sixtp-dom-parsers.h"
|
||||
|
||||
static QofLogModule log_module = GNC_MOD_SX;
|
||||
#define LOG_MOD "gnc.backend.file.sx"
|
||||
static QofLogModule log_module = LOG_MOD;
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN LOG_MOD
|
||||
|
||||
/**
|
||||
* The XML output should look something like:
|
||||
@ -131,6 +133,7 @@ static QofLogModule log_module = GNC_MOD_SX;
|
||||
#define SX_END "sx:end"
|
||||
#define SX_TEMPL_ACCT "sx:templ-acct"
|
||||
#define SX_FREQSPEC "sx:freqspec"
|
||||
#define SX_SCHEDULE "sx:schedule"
|
||||
#define SX_SLOTS "sx:slots"
|
||||
#define SX_DEFER_INSTANCE "sx:deferredInstance"
|
||||
|
||||
@ -143,6 +146,7 @@ static QofLogModule log_module = GNC_MOD_SX;
|
||||
#define GNC_SCHEDXACTION_TAG "gnc:schedxaction"
|
||||
|
||||
const gchar *schedxaction_version_string = "1.0.0";
|
||||
const gchar *schedxaction_version2_string = "2.0.0";
|
||||
|
||||
xmlNodePtr
|
||||
gnc_schedXaction_dom_tree_create(SchedXaction *sx)
|
||||
@ -257,6 +261,8 @@ struct sx_pdata
|
||||
{
|
||||
SchedXaction *sx;
|
||||
QofBook *book;
|
||||
gboolean saw_freqspec;
|
||||
gboolean saw_recurrence;
|
||||
};
|
||||
|
||||
static
|
||||
@ -415,22 +421,45 @@ sx_end_handler( xmlNodePtr node, gpointer sx_pdata )
|
||||
return sx_set_date( node, sx, xaccSchedXactionSetEndDate );
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
static gboolean
|
||||
sx_freqspec_handler( xmlNodePtr node, gpointer sx_pdata )
|
||||
{
|
||||
struct sx_pdata *pdata = sx_pdata;
|
||||
SchedXaction *sx = pdata->sx;
|
||||
FreqSpec *fs;
|
||||
GList *schedule;
|
||||
|
||||
g_return_val_if_fail( node, FALSE );
|
||||
|
||||
fs = dom_tree_to_freqSpec( node, pdata->book );
|
||||
xaccSchedXactionSetFreqSpec( sx, fs );
|
||||
xaccSchedXactionSetFreqSpec(sx, dom_tree_to_freqSpec(node, pdata->book));
|
||||
|
||||
schedule = dom_tree_freqSpec_to_recurrences(node, pdata->book);
|
||||
gnc_sx_set_schedule(sx, schedule);
|
||||
for (; schedule != NULL; schedule = schedule->next)
|
||||
{
|
||||
g_debug("parsed from freqspec [%s]", recurrenceToString((Recurrence*)schedule->data));
|
||||
}
|
||||
pdata->saw_freqspec = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sx_recurrence_handler(xmlNodePtr node, gpointer _pdata)
|
||||
{
|
||||
struct sx_pdata *parsing_data = _pdata;
|
||||
GList *schedule;
|
||||
|
||||
g_return_val_if_fail(node, FALSE);
|
||||
|
||||
//schedule = dom_tree_to_recurrence(node);
|
||||
//g_return_val_if_fail(schedule, FALSE);
|
||||
|
||||
//gnc_sx_set_schedule(parsing_data->sx, schedule);
|
||||
parsing_data->saw_recurrence = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
sx_defer_last_handler( xmlNodePtr node, gpointer gpTSD )
|
||||
@ -590,7 +619,8 @@ struct dom_tree_handler sx_dom_handlers[] = {
|
||||
{ SX_REM_OCCUR, sx_remOccur_handler, 0, 0 },
|
||||
{ SX_END, sx_end_handler, 0, 0 },
|
||||
{ SX_TEMPL_ACCT, sx_templ_acct_handler, 0, 0 },
|
||||
{ SX_FREQSPEC, sx_freqspec_handler, 1, 0 },
|
||||
{ SX_FREQSPEC, sx_freqspec_handler, 0, 0 },
|
||||
{ SX_SCHEDULE, sx_recurrence_handler, 0, 0 },
|
||||
{ SX_DEFER_INSTANCE, sx_defer_inst_handler, 0, 0 },
|
||||
{ SX_SLOTS, sx_slots_handler, 0, 0 },
|
||||
{ NULL, NULL, 0, 0 }
|
||||
@ -620,34 +650,58 @@ gnc_schedXaction_end_handler(gpointer data_for_children,
|
||||
|
||||
sx = xaccSchedXactionMalloc( gdata->bookdata );
|
||||
|
||||
/* FIXME: this should be removed somewhere near 1.8 release time. */
|
||||
{
|
||||
/* This is the just-created template acct. It can safely be
|
||||
removed, as we either will find or don't have a relevent
|
||||
template_acct. */
|
||||
xaccAccountBeginEdit (sx->template_acct);
|
||||
xaccAccountDestroy( sx->template_acct );
|
||||
sx->template_acct = NULL;
|
||||
}
|
||||
|
||||
memset(&sx_pdata, 0, sizeof(sx_pdata));
|
||||
sx_pdata.sx = sx;
|
||||
sx_pdata.book = gdata->bookdata;
|
||||
|
||||
g_assert( sx_dom_handlers != NULL );
|
||||
|
||||
successful = dom_tree_generic_parse( tree, sx_dom_handlers, &sx_pdata );
|
||||
|
||||
if ( successful )
|
||||
if (!successful)
|
||||
{
|
||||
gdata->cb( tag, gdata->parsedata, sx );
|
||||
}
|
||||
else
|
||||
{
|
||||
PERR ("failed to parse scheduled xaction");
|
||||
g_critical("failed to parse scheduled xaction");
|
||||
xmlElemDump( stdout, NULL, tree );
|
||||
xaccSchedXactionFree( sx );
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (tree->properties)
|
||||
{
|
||||
gchar *sx_name = xaccSchedXactionGetName(sx);
|
||||
xmlAttr *attr;
|
||||
for (attr = tree->properties; attr != NULL; attr = attr->next)
|
||||
{
|
||||
xmlChar *attr_value = attr->children->content;
|
||||
g_debug("sx attribute name[%s] value[%s]", attr->name, attr_value);
|
||||
if (strcmp(attr->name, "version") != 0)
|
||||
{
|
||||
g_warning("unknown sx attribute [%s]", attr->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
// if version == 1.0.0: ensure freqspec, no recurrence
|
||||
// if version == 2.0.0: ensure recurrence, no freqspec.
|
||||
if (strcmp(attr_value, schedxaction_version_string) == 0)
|
||||
{
|
||||
if (!sx_pdata.saw_freqspec)
|
||||
g_critical("did not see freqspec in version 1 sx [%s]", sx_name);
|
||||
if (sx_pdata.saw_recurrence)
|
||||
g_warning("saw recurrence in supposedly version 1 sx [%s]", sx_name);
|
||||
}
|
||||
|
||||
if (strcmp(attr_value, schedxaction_version2_string) == 0)
|
||||
{
|
||||
if (sx_pdata.saw_freqspec)
|
||||
g_warning("saw freqspec in version 2 sx [%s]", sx_name);
|
||||
if (!sx_pdata.saw_recurrence)
|
||||
g_critical("did not find recurrence in version 2 sx [%s]", sx_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// generic_callback -> book_callback: insert the SX in the book
|
||||
gdata->cb( tag, gdata->parsedata, sx );
|
||||
|
||||
/* FIXME: this should be removed somewhere near 1.8 release time. */
|
||||
if ( sx->template_acct == NULL )
|
||||
{
|
||||
@ -668,21 +722,18 @@ gnc_schedXaction_end_handler(gpointer data_for_children,
|
||||
ag = gnc_book_get_template_group(book);
|
||||
if ( ag == NULL )
|
||||
{
|
||||
PERR( "Error getting template account group "
|
||||
"from being-parsed Book." );
|
||||
g_warning( "Error getting template account group from being-parsed Book." );
|
||||
xmlFreeNode( tree );
|
||||
return FALSE;
|
||||
}
|
||||
acct = xaccGetAccountFromName( ag, id );
|
||||
if ( acct == NULL )
|
||||
acct = xaccGetAccountFromName(ag, id);
|
||||
if (acct == NULL)
|
||||
{
|
||||
PERR( "Error getting template account "
|
||||
"with name \"%s\"", id );
|
||||
g_warning("no template account with name [%s]", id);
|
||||
xmlFreeNode( tree );
|
||||
return FALSE;
|
||||
}
|
||||
DEBUG( "Got template account with name \"%s\" for "
|
||||
"SX with GUID \"%s\"",
|
||||
g_debug("template account name [%s] for SX with GUID [%s]",
|
||||
xaccAccountGetName( acct ), id );
|
||||
|
||||
/* FIXME: free existing template account.
|
||||
@ -693,6 +744,8 @@ gnc_schedXaction_end_handler(gpointer data_for_children,
|
||||
|
||||
sx->template_acct = acct;
|
||||
}
|
||||
|
||||
done:
|
||||
xmlFreeNode( tree );
|
||||
|
||||
return successful;
|
||||
@ -731,7 +784,7 @@ tt_act_handler( xmlNodePtr node, gpointer data )
|
||||
applies for
|
||||
SchedXaction.c:xaccSchedXactionInit... */
|
||||
com = gnc_commodity_new( txd->book,
|
||||
"template", "template",
|
||||
"template", "template",
|
||||
"template", "template",
|
||||
1 );
|
||||
xaccAccountSetCommodity( acc, com );
|
||||
@ -813,7 +866,7 @@ gnc_template_transaction_end_handler(gpointer data_for_children,
|
||||
}
|
||||
else
|
||||
{
|
||||
PERR ("failed to parse template transaction");
|
||||
g_warning("failed to parse template transaction");
|
||||
xmlElemDump( stdout, NULL, tree );
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ gnc_commodity* dom_tree_to_commodity_ref(xmlNodePtr node, QofBook *book);
|
||||
gnc_commodity *dom_tree_to_commodity_ref_no_engine(xmlNodePtr node, QofBook *);
|
||||
|
||||
FreqSpec* dom_tree_to_freqSpec( xmlNodePtr node, QofBook *book);
|
||||
GList* dom_tree_freqSpec_to_recurrences(xmlNodePtr node, QofBook *book);
|
||||
Recurrence* dom_tree_to_recurrence(xmlNodePtr node);
|
||||
|
||||
Timespec dom_tree_to_timespec(xmlNodePtr node);
|
||||
|
@ -74,6 +74,7 @@ test_xml_account_SOURCES = \
|
||||
${top_srcdir}/src/backend/file/gnc-account-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-lot-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-schedxaction-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-recurrence-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-freqspec-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-transaction-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-commodity-xml-v2.c \
|
||||
@ -92,6 +93,7 @@ test_xml_commodity_SOURCES = \
|
||||
${top_srcdir}/src/backend/file/gnc-account-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-lot-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-schedxaction-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-recurrence-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-freqspec-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-transaction-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-commodity-xml-v2.c \
|
||||
@ -110,6 +112,7 @@ test_xml_pricedb_SOURCES = \
|
||||
${top_srcdir}/src/backend/file/gnc-account-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-lot-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-schedxaction-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-recurrence-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-freqspec-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-transaction-xml-v2.c \
|
||||
${top_srcdir}/src/backend/file/gnc-commodity-xml-v2.c \
|
||||
|
@ -112,17 +112,38 @@ TODO
|
||||
|
||||
- use Recurrence instead of FreqSpec
|
||||
! - [ ] XML migration, handling
|
||||
- xml:freqSpec -> obj:Recurrence
|
||||
- [ ] none (Recurrence doesn't support)
|
||||
- [x] once
|
||||
- [x] daily
|
||||
- [ ] daily [m-f] (composite)
|
||||
- [x] weekly, single
|
||||
- [ ] weekly, multiple (composite)
|
||||
- [x] monthly (+quarterly, tri-anually, semi-annually, yearly)
|
||||
- [ ] semi-monthly (composite)
|
||||
- gnc-frequency
|
||||
! - [x] Support Recurrence
|
||||
- [x] in
|
||||
- [x] out
|
||||
! - [x] Support 'last-day-of-month'
|
||||
- [x] simplify
|
||||
- [x] remove daily [m-f] (-> weekly)
|
||||
- [x] remove biweekly page (-> weekly)
|
||||
- [x] remove > monthly pages (-> monthly)
|
||||
- [ ] clean up, reformat source
|
||||
- dialog-sx-editor
|
||||
- [ ] gnc_sxed_check_changed
|
||||
- [ ] gnc_sxed_check_consistent
|
||||
- [ ] gnc_sxed_update_cal
|
||||
- [x] gnc_sxed_save_sx
|
||||
- [ ] remove FreqSpec code
|
||||
- [ ] SX code
|
||||
- [ ] src/gnome/druid-acct-period.c
|
||||
- gnc-frequency
|
||||
! - [ ] Use Recurrence
|
||||
! - [ ] Support 'last-day-of-month'
|
||||
- [ ] clean up, reformat
|
||||
|
||||
- since-last-run
|
||||
! - [ ] save/restore dialog window size
|
||||
- [ ] "reminder" instances show number of days until due
|
||||
- [ ] "Find unfinished" button; count; sensitize Ok as function of unfinished.
|
||||
! - [x] rewrite adapter (re-)population logic
|
||||
- [x] move "effect_change" up to app-utils/, test.
|
||||
- [x] move state-change up to app-utils
|
||||
|
@ -97,7 +97,6 @@ noinst_HEADERS = \
|
||||
FreqSpecP.h \
|
||||
GroupP.h \
|
||||
QueryP.h \
|
||||
SchedXactionP.h \
|
||||
ScrubP.h \
|
||||
SplitP.h \
|
||||
SX-book.h \
|
||||
|
@ -1,6 +1,6 @@
|
||||
/********************************************************************\
|
||||
* SchedXaction.c -- Scheduled Transaction implementation. *
|
||||
* Copyright (C) 2001 Joshua Sled <jsled@asynchronous.org> *
|
||||
* Copyright (C) 2001,2007 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 *
|
||||
@ -37,7 +37,6 @@
|
||||
#include "SX-book.h"
|
||||
#include "SX-ttinfo.h"
|
||||
#include "SchedXaction.h"
|
||||
#include "SchedXactionP.h"
|
||||
#include "Transaction.h"
|
||||
#include "gnc-engine.h"
|
||||
|
||||
@ -57,6 +56,7 @@ xaccSchedXactionInit(SchedXaction *sx, QofBook *book)
|
||||
|
||||
qof_instance_init (&sx->inst, GNC_ID_SCHEDXACTION, book);
|
||||
|
||||
sx->schedule = NULL;
|
||||
sx->freq = xaccFreqSpecMalloc(book);
|
||||
|
||||
g_date_clear( &sx->last_date, 1 );
|
||||
@ -74,13 +74,12 @@ xaccSchedXactionInit(SchedXaction *sx, QofBook *book)
|
||||
|
||||
/* create a new template account for our splits */
|
||||
sx->template_acct = xaccMallocAccount(book);
|
||||
/* THREAD-UNSAFE */
|
||||
xaccAccountSetName( sx->template_acct,
|
||||
guid_to_string( &sx->inst.entity.guid ));
|
||||
xaccAccountSetCommodity
|
||||
(sx->template_acct,
|
||||
gnc_commodity_new( book,
|
||||
"template", "template",
|
||||
"template", "template",
|
||||
"template", "template", 1 ) );
|
||||
xaccAccountSetType( sx->template_acct, ACCT_TYPE_BANK );
|
||||
ag = gnc_book_get_template_group( book );
|
||||
@ -111,7 +110,6 @@ sxprivTransMapDelete( gpointer data, gpointer user_data )
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
delete_template_trans(SchedXaction *sx)
|
||||
{
|
||||
@ -230,6 +228,22 @@ xaccSchedXactionSetFreqSpec( SchedXaction *sx, FreqSpec *fs )
|
||||
gnc_sx_commit_edit(sx);
|
||||
}
|
||||
|
||||
GList*
|
||||
gnc_sx_get_schedule(SchedXaction *sx)
|
||||
{
|
||||
return sx->schedule;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_sx_set_schedule(SchedXaction *sx, GList *schedule)
|
||||
{
|
||||
g_return_if_fail(sx && schedule);
|
||||
gnc_sx_begin_edit(sx);
|
||||
sx->schedule = schedule;
|
||||
qof_instance_set_dirty(&sx->inst);
|
||||
gnc_sx_commit_edit(sx);
|
||||
}
|
||||
|
||||
gchar *
|
||||
xaccSchedXactionGetName( SchedXaction *sx )
|
||||
{
|
||||
@ -287,7 +301,7 @@ xaccSchedXactionSetEndDate( SchedXaction *sx, GDate *newEnd )
|
||||
* This warning is only human readable - the caller
|
||||
* doesn't know the call failed. This is bad
|
||||
*/
|
||||
PWARN( "New end date before start date" );
|
||||
g_critical("New end date before start date");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -346,7 +360,7 @@ xaccSchedXactionSetRemOccur( SchedXaction *sx,
|
||||
/* FIXME This condition can be tightened up */
|
||||
if ( numRemain > sx->num_occurances_total )
|
||||
{
|
||||
PWARN("The number remaining is greater than the total occurrences");
|
||||
g_warning("The number remaining is greater than the total occurrences");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -40,15 +40,78 @@
|
||||
#include <glib.h>
|
||||
#include "qof.h"
|
||||
#include "FreqSpec.h"
|
||||
#include "Recurrence.h"
|
||||
#include "gnc-engine.h"
|
||||
|
||||
#define GNC_IS_SX(obj) (QOF_CHECK_TYPE((obj), GNC_ID_SCHEDXACTION))
|
||||
#define GNC_SX(obj) (QOF_CHECK_CAST((obj), GNC_ID_SCHEDXACTION, SchedXaction))
|
||||
|
||||
typedef struct _SchedXaction SchedXaction;
|
||||
|
||||
/**
|
||||
* The SchedXaction data.
|
||||
*/
|
||||
typedef struct gncp_SchedXaction SchedXaction;
|
||||
* A single scheduled transaction.
|
||||
*
|
||||
* Scheduled transactions have a list of transactions, and a frequency
|
||||
* [and associated date anchors] with which they are scheduled.
|
||||
*
|
||||
* Things that make sense to have in a template transaction:
|
||||
* [not] Date [though eventually some/multiple template transactions
|
||||
* might have relative dates].
|
||||
* Memo
|
||||
* Account
|
||||
* Funds In/Out... or an expr involving 'amt' [A, x, y, a?] for
|
||||
* variable expenses.
|
||||
*
|
||||
* Template transactions are instantiated by:
|
||||
* . copying the fields of the template
|
||||
* . setting the date to the calculated "due" date.
|
||||
*
|
||||
* We should be able to use the GeneralLedger [or, yet-another-subtype
|
||||
* of the internal ledger] for this editing.
|
||||
**/
|
||||
struct _SchedXaction
|
||||
{
|
||||
QofInstance inst;
|
||||
gchar *name;
|
||||
|
||||
GList *schedule;
|
||||
FreqSpec *freq;
|
||||
|
||||
GDate last_date;
|
||||
|
||||
GDate start_date;
|
||||
/* if end_date is invalid, then no end. */
|
||||
GDate end_date;
|
||||
|
||||
/* if num_occurances_total == 0, then no limit */
|
||||
gint num_occurances_total;
|
||||
/* reminaing occurances are as-of the 'last_date'. */
|
||||
gint num_occurances_remain;
|
||||
|
||||
/* the current instance-count of the SX. */
|
||||
gint instance_num;
|
||||
|
||||
gboolean enabled;
|
||||
gboolean autoCreateOption;
|
||||
gboolean autoCreateNotify;
|
||||
gint advanceCreateDays;
|
||||
gint advanceRemindDays;
|
||||
|
||||
Account *template_acct;
|
||||
|
||||
/** The list of deferred SX instances. This list is of temporalStateData
|
||||
* instances. */
|
||||
GList /* <temporalStateData*> */ *deferredList;
|
||||
};
|
||||
|
||||
/** Just the variable temporal bits from the SX structure. */
|
||||
typedef struct _temporalStateData {
|
||||
GDate last_date;
|
||||
gint num_occur_rem;
|
||||
gint num_inst;
|
||||
} temporalStateData;
|
||||
|
||||
#define xaccSchedXactionSetGUID(X,G) qof_entity_set_guid(QOF_ENTITY(X),(G))
|
||||
|
||||
/**
|
||||
* Creates and initializes a scheduled transaction.
|
||||
@ -63,6 +126,11 @@ void xaccSchedXactionFree( SchedXaction *sx );
|
||||
void gnc_sx_begin_edit (SchedXaction *sx);
|
||||
void gnc_sx_commit_edit (SchedXaction *sx);
|
||||
|
||||
/** @return GList<Recurrence*> **/
|
||||
GList* gnc_sx_get_schedule(SchedXaction *sx);
|
||||
/** @param[in] schedule A GList<Recurrence*> **/
|
||||
void gnc_sx_set_schedule(SchedXaction *sx, GList *schedule);
|
||||
|
||||
FreqSpec *xaccSchedXactionGetFreqSpec( SchedXaction *sx );
|
||||
/**
|
||||
* The FreqSpec is given to the SchedXaction for mem mgmt; it should
|
||||
@ -162,7 +230,7 @@ void *gnc_sx_clone_temporal_state( void *stateData );
|
||||
/** @} */
|
||||
|
||||
/** \brief Returns the next occurance of a scheduled transaction.
|
||||
|
||||
*
|
||||
* If the transaction hasn't occured, then it's based off the start date.
|
||||
* Otherwise, it's based off the last-occurance date.
|
||||
*
|
||||
|
@ -1,93 +0,0 @@
|
||||
/********************************************************************\
|
||||
* SchedXactionP.h -- Scheduled Transaction private header *
|
||||
* Copyright (C) 2001 Linux Developers Group *
|
||||
* *
|
||||
* 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 *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
#ifndef XACC_SCHEDXACTION_P_H
|
||||
#define XACC_SCHEDXACTION_P_H
|
||||
|
||||
#include "SchedXaction.h"
|
||||
|
||||
/**
|
||||
* A single scheduled transaction.
|
||||
*
|
||||
* Scheduled transactions have a list of transactions, and a frequency
|
||||
* [and associated date anchors] with which they are scheduled.
|
||||
*
|
||||
* Things that make sense to have in a template transaction:
|
||||
* [not] Date [though eventually some/multiple template transactions
|
||||
* might have relative dates].
|
||||
* Memo
|
||||
* Account
|
||||
* Funds In/Out... or an expr involving 'amt' [A, x, y, a?] for
|
||||
* variable expenses.
|
||||
*
|
||||
* Template transactions are instantiated by:
|
||||
* . copying the fields of the template
|
||||
* . setting the date to the calculated "due" date.
|
||||
*
|
||||
* We should be able to use the GeneralLedger [or, yet-another-subtype
|
||||
* of the internal ledger] for this editing.
|
||||
**/
|
||||
struct gncp_SchedXaction
|
||||
{
|
||||
QofInstance inst;
|
||||
gchar *name;
|
||||
|
||||
FreqSpec *freq;
|
||||
|
||||
GDate last_date;
|
||||
|
||||
GDate start_date;
|
||||
/* if end_date is invalid, then no end. */
|
||||
GDate end_date;
|
||||
|
||||
/* if num_occurances_total == 0, then no limit */
|
||||
gint num_occurances_total;
|
||||
/* reminaing occurances are as-of the 'last_date'. */
|
||||
gint num_occurances_remain;
|
||||
|
||||
/* the current instance-count of the SX. */
|
||||
gint instance_num;
|
||||
|
||||
gboolean enabled;
|
||||
gboolean autoCreateOption;
|
||||
gboolean autoCreateNotify;
|
||||
gint advanceCreateDays;
|
||||
gint advanceRemindDays;
|
||||
|
||||
Account *template_acct;
|
||||
|
||||
/** The list of deferred SX instances. This list is of temporalStateData
|
||||
* instances. */
|
||||
GList /* <temporalStateData*> */ *deferredList;
|
||||
};
|
||||
|
||||
/** Just the variable temporal bits from the SX structure. */
|
||||
typedef struct _temporalStateData {
|
||||
GDate last_date;
|
||||
gint num_occur_rem;
|
||||
gint num_inst;
|
||||
} temporalStateData;
|
||||
|
||||
#define xaccSchedXactionSetGUID(X,G) qof_entity_set_guid(QOF_ENTITY(X),(G))
|
||||
|
||||
#endif /* XACC_SCHEDXACTION_P_H */
|
@ -34,7 +34,6 @@
|
||||
#include "TransactionP.h"
|
||||
#include "gnc-commodity.h"
|
||||
#include "gnc-lot-p.h"
|
||||
#include "SchedXactionP.h"
|
||||
#include "FreqSpecP.h"
|
||||
#include "gnc-pricedb-p.h"
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -26,6 +26,7 @@
|
||||
#define GNC_FREQUENCY_H
|
||||
|
||||
#include "gnc-date-edit.h"
|
||||
#include "Recurrence.h"
|
||||
#include "FreqSpec.h"
|
||||
|
||||
#define GNC_TYPE_FREQUENCY (gnc_frequency_get_type())
|
||||
@ -41,54 +42,55 @@
|
||||
**/
|
||||
typedef struct _GncFrequency
|
||||
{
|
||||
GtkVBox widget;
|
||||
|
||||
GtkVBox *vb;
|
||||
GtkNotebook *nb;
|
||||
GtkComboBox *freqComboBox;
|
||||
GNCDateEdit *startDate;
|
||||
GladeXML *gxml;
|
||||
GtkVBox widget;
|
||||
GtkVBox *vb;
|
||||
GtkNotebook *nb;
|
||||
GtkComboBox *freqComboBox;
|
||||
GNCDateEdit *startDate;
|
||||
GladeXML *gxml;
|
||||
} GncFrequency;
|
||||
|
||||
typedef struct _GncFrequencyClass
|
||||
{
|
||||
GtkVBoxClass parent_class;
|
||||
GtkVBoxClass parent_class;
|
||||
|
||||
void (*changed) (GncFrequency *gf);
|
||||
void (*changed) (GncFrequency *gf);
|
||||
} GncFrequencyClass;
|
||||
|
||||
struct pageDataTuple
|
||||
{
|
||||
int idx;
|
||||
UIFreqType uiFTVal;
|
||||
char *name;
|
||||
int idx;
|
||||
UIFreqType uiFTVal;
|
||||
char *name;
|
||||
};
|
||||
|
||||
GType gnc_frequency_get_type( void );
|
||||
GType gnc_frequency_get_type(void);
|
||||
|
||||
/**
|
||||
* Create a new GncFrequencey widget.
|
||||
* The menus and panels will be initialized to correspond to the
|
||||
* settings in the FreqSpec, and the date window will show the
|
||||
* indicated date. Either or both may be NULL.
|
||||
* For the default freq spec widget, use 'NULL'.
|
||||
* Create a new GncFrequencey widget, reflecting the given FreqSpec \a fs and
|
||||
* starting on \a start_date. Either or both may be NULL for reasonable
|
||||
* defaults.
|
||||
**/
|
||||
GtkWidget* gnc_frequency_new(FreqSpec *fs, GDate *start_date);
|
||||
void gnc_frequency_init( GncFrequency *gf );
|
||||
GtkWidget* gnc_frequency_new_from_recurrence(GList *recurrences, GDate *start_date);
|
||||
|
||||
void gnc_frequency_init(GncFrequency *gf);
|
||||
|
||||
/**
|
||||
* Change the given GncFrequency with the given FreqSpec and GDate.
|
||||
* Change the given GncFrequency with the given FreqSpec and GDate.
|
||||
* If the FreqSpec is NULL, then no change is made to the widget menus.
|
||||
* If the date is NULL, then no change is made to the widget date field.
|
||||
**/
|
||||
void gnc_frequency_setup( GncFrequency *gf, FreqSpec *fs, GDate *date );
|
||||
void gnc_frequency_setup(GncFrequency *gf, FreqSpec *fs, GDate *date);
|
||||
void gnc_frequency_setup_recurrence(GncFrequency *gf, GList *recurrences, GDate *start_date);
|
||||
|
||||
/**
|
||||
* Saves the state of the GNCFrequenecy widget.
|
||||
* Saves the state of the GncFrequency widget.
|
||||
* Updates the given FreqSpec if it's not NULL.
|
||||
* Places the date in outDate, if it's not NULL.
|
||||
**/
|
||||
void gnc_frequency_save_state( GncFrequency *gf, FreqSpec *fs, GDate *outDate);
|
||||
void gnc_frequency_save_state(GncFrequency *gf, FreqSpec *fs, GDate *outDate);
|
||||
void gnc_frequency_save_to_recurrence(GncFrequency *gf, GList **recurrences, GDate *out_start_date);
|
||||
|
||||
/**
|
||||
* Set the label text for the frequency option menu. In the current
|
||||
@ -102,6 +104,4 @@ void gnc_frequency_set_frequency_label_text (GncFrequency *gf, const gchar *txt)
|
||||
*/
|
||||
void gnc_frequency_set_date_label_text (GncFrequency *gf, const gchar *txt);
|
||||
|
||||
void gnc_frequency_setup_default( GncFrequency *gf, FreqSpec *fs, GDate *date );
|
||||
|
||||
#endif /* !defined( GNC_FREQUENCY_H ) */
|
||||
|
@ -972,6 +972,7 @@ gnc_sxed_save_sx( GncSxEditorDialog *sxed )
|
||||
FreqSpec *fs;
|
||||
GDate gdate;
|
||||
GString *str;
|
||||
GList *schedule = NULL;
|
||||
|
||||
fs = xaccSchedXactionGetFreqSpec( sxed->sx );
|
||||
gnc_frequency_save_state( sxed->gncfreq, fs, &gdate );
|
||||
@ -980,10 +981,13 @@ gnc_sxed_save_sx( GncSxEditorDialog *sxed )
|
||||
xaccFreqSpecGetFreqStr( fs, str );
|
||||
g_debug("fs: %s", str->str);
|
||||
|
||||
gnc_frequency_save_to_recurrence(sxed->gncfreq, &schedule, &gdate);
|
||||
gnc_sx_set_schedule(sxed->sx, schedule);
|
||||
g_debug("recurrences parsed [%s]", recurrenceListToString(schedule));
|
||||
|
||||
/* now that we have it, set the start date */
|
||||
xaccSchedXactionSetStartDate( sxed->sx, &gdate );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1259,10 +1263,13 @@ schedXact_editor_create_freq_sel( GncSxEditorDialog *sxed )
|
||||
GtkBox *b;
|
||||
|
||||
b = GTK_BOX(glade_xml_get_widget( sxed->gxml, "gncfreq_hbox" ));
|
||||
sxed->gncfreq =
|
||||
/*sxed->gncfreq =
|
||||
GNC_FREQUENCY( gnc_frequency_new( xaccSchedXactionGetFreqSpec(sxed->sx),
|
||||
xaccSchedXactionGetStartDate(sxed->sx) ) );
|
||||
g_assert( sxed->gncfreq );
|
||||
xaccSchedXactionGetStartDate(sxed->sx) ) );*/
|
||||
sxed->gncfreq =
|
||||
GNC_FREQUENCY(gnc_frequency_new_from_recurrence(gnc_sx_get_schedule(sxed->sx),
|
||||
xaccSchedXactionGetStartDate(sxed->sx)));
|
||||
g_assert(sxed->gncfreq);
|
||||
g_signal_connect( sxed->gncfreq, "changed",
|
||||
G_CALLBACK(gnc_sxed_freq_changed),
|
||||
sxed );
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user