r15696 - gnucash/trunk/src - Change Mortgage/Loan druid to generate SXes with Recurrences, not FreqSpecs.

Josh Sled jsled at cvs.gnucash.org
Thu Mar 8 21:44:04 EST 2007


Author: jsled
Date: 2007-03-08 21:44:03 -0500 (Thu, 08 Mar 2007)
New Revision: 15696
Trac: http://svn.gnucash.org/trac/changeset/15696

Modified:
   gnucash/trunk/src/doc/sx.rst
   gnucash/trunk/src/gnome/druid-loan.c
Log:
Change Mortgage/Loan druid to generate SXes with Recurrences, not FreqSpecs.


Modified: gnucash/trunk/src/doc/sx.rst
===================================================================
--- gnucash/trunk/src/doc/sx.rst	2007-03-08 23:31:33 UTC (rev 15695)
+++ gnucash/trunk/src/doc/sx.rst	2007-03-09 02:44:03 UTC (rev 15696)
@@ -105,7 +105,7 @@
   - [#] type+ui-type -> type
 
 - use Recurrence instead of FreqSpec
-! - [ ] load druid
+! - [x] load druid
 ! - [x] sx-from-trans, <http://bugzilla.gnome.org/show_bug.cgi?id=412633>
 ! - [x] XML migration, handling
     - xml:freqSpec -> obj:Recurrence
@@ -141,6 +141,10 @@
     - [x] More compact recurrenceListToString(...).
   - [ ] remove FreqSpec code
     - [ ] SX code
+      - [ ] engine
+      - [ ] backend
+      - [ ] gnc-frequency
+      - [ ] gnc-dense-cal-store
     - [x] src/gnome/druid-acct-period.c
 
 - gnc_frequency

Modified: gnucash/trunk/src/gnome/druid-loan.c
===================================================================
--- gnucash/trunk/src/gnome/druid-loan.c	2007-03-08 23:31:33 UTC (rev 15695)
+++ gnucash/trunk/src/gnome/druid-loan.c	2007-03-09 02:44:03 UTC (rev 15696)
@@ -1,7 +1,7 @@
 /********************************************************************\
  * druid-loan.c : A Gnome Druid for setting up loan-repayment       *
  *     scheduled transactions.                                      *
- * Copyright (C) 2002 Joshua Sled <jsled at asynchronous.org>          *
+ * Copyright (C) 2002,2007 Joshua Sled <jsled at asynchronous.org>     *
  * Copyright (C) 2006 David Hampton <hampton at employees.org>         *
  *                                                                  *
  * This program is free software; you can redistribute it and/or    *
@@ -45,7 +45,6 @@
 #include "gnc-component-manager.h"
 #include "dialog-utils.h"
 #include "Account.h"
-#include "FreqSpec.h"
 #include "gnc-ui.h"
 #include "gnc-gdate-utils.h"
 #include "gnc-gui-query.h"
@@ -141,8 +140,9 @@
         Account *to;
         Account *from; /* If NULL { If throughEscrowP, then through escrowAcct };
                         * else: undefined. */
-        FreqSpec *fs;  /* If NULL, part of repayment; otherwise: defined
-                        * here. */
+        GList *schedule;
+    /* If NULL, part of repayment; otherwise: defined
+     * here. */
         GDate *startDate;
 } RepayOptData;
 
@@ -211,7 +211,7 @@
         gnc_numeric principal;
         float interestRate;
         LoanType type;
-        FreqSpec *loanFreq;
+        GList *loan_schedule;
         GDate *startDate;
         GDate *varStartDate;
         int numPer;
@@ -224,7 +224,7 @@
         Account *repPriAcct;
         Account *repIntAcct;
         Account *escrowAcct;
-        FreqSpec *repFreq;
+        GList *repayment_schedule;
         GDate *repStartDate;
 
         int repayOptCount;
@@ -322,8 +322,8 @@
   gchar *name;
   /** The start, last-occurred and end dates. */
   GDate start, last, end;
-  /** The SX FreqSpec */
-  FreqSpec *freq;
+  /** The SX schedule */
+  GList *schedule;
   /** The current 'instance-num' count. */
   gint instNum;
   /** The main/source transaction being created. */
@@ -800,10 +800,13 @@
         ldd->ld.startDate = g_date_new();
         ldd->ld.varStartDate = g_date_new();
         g_date_set_time_t( ldd->ld.startDate, time(NULL) );
-        ldd->ld.loanFreq  = xaccFreqSpecMalloc( gnc_get_current_book() );
-        ldd->ld.repFreq   = xaccFreqSpecMalloc( gnc_get_current_book() );
-        xaccFreqSpecSetMonthly( ldd->ld.repFreq, ldd->ld.startDate, 1 );
-        xaccFreqSpecSetUIType( ldd->ld.repFreq, UIFREQ_MONTHLY );
+        ldd->ld.loan_schedule= NULL;
+        ldd->ld.repayment_schedule = NULL;
+        {
+                Recurrence *r = g_new0(Recurrence, 1);
+                recurrenceSet(r, 1, PERIOD_MONTH, ldd->ld.startDate);
+                ldd->ld.repayment_schedule = g_list_append(ldd->ld.repayment_schedule, r);
+        }
 
         ldd->ld.repMemo = g_strdup( _("Loan") );
         ldd->ld.repAmount = NULL;
@@ -829,7 +832,7 @@
                 optData->amount         = 0.0;
                 optData->throughEscrowP = REPAY_DEFAULTS[i].escrowDefault;
                 optData->specSrcAcctP   = REPAY_DEFAULTS[i].specSrcAcctDefault;
-                optData->fs             = NULL;
+                optData->schedule       = NULL;
                 optData->startDate      = NULL;
         }
 }
@@ -986,7 +989,7 @@
 
                 g_date_free( ldd->ld.startDate );
                 g_date_free( ldd->ld.varStartDate );
-                xaccFreqSpecFree( ldd->ld.loanFreq );
+                recurrenceListFree(&ldd->ld.loan_schedule);
 
                 if ( ldd->ld.repMemo )
                         g_free( ldd->ld.repMemo );
@@ -1001,8 +1004,8 @@
                         if ( rod->startDate )
                                 g_date_free( rod->startDate );
 
-                        if ( rod->fs )
-                                xaccFreqSpecFree( rod->fs );
+                        if (rod->schedule != NULL)
+                                recurrenceListFree(&rod->schedule);
 
                         g_free( ldd->ld.repayOpts[i] );
                         g_free( ldd->repayOptsUI[i] );
@@ -1164,9 +1167,10 @@
         ldd->ld.interestRate = gtk_spin_button_get_value( ldd->prmIrateSpin );
         ldd->ld.type = gtk_combo_box_get_active( ldd->prmType );
         if ( ldd->ld.type != GNC_FIXED ) {
-                gnc_frequency_save_state( ldd->prmVarGncFreq,
-                                          ldd->ld.loanFreq,
-                                          ldd->ld.varStartDate );
+                recurrenceListFree(&ldd->ld.loan_schedule);
+                gnc_frequency_save_to_recurrence(ldd->prmVarGncFreq,
+                                                 &ldd->ld.loan_schedule,
+                                                 ldd->ld.varStartDate);
         }
 
         /* start date */
@@ -1206,9 +1210,9 @@
         gtk_spin_button_set_value( ldd->prmIrateSpin, ldd->ld.interestRate );
         gtk_combo_box_set_active( ldd->prmType, ldd->ld.type );
         if ( ldd->ld.type != GNC_FIXED ) {
-                gnc_frequency_setup( ldd->prmVarGncFreq,
-                                     ldd->ld.loanFreq,
-                                     ldd->ld.varStartDate );
+                gnc_frequency_setup_recurrence(ldd->prmVarGncFreq,
+                                               ldd->ld.loan_schedule,
+                                               ldd->ld.varStartDate);
         }
 
         /* start date */
@@ -1324,9 +1328,10 @@
                                    "\"interest\" account.") );
                 return TRUE;
         }
-        gnc_frequency_save_state( ldd->repGncFreq,
-                                  ldd->ld.repFreq,
-                                  ldd->ld.repStartDate );
+        recurrenceListFree(&ldd->ld.repayment_schedule);
+        gnc_frequency_save_to_recurrence(ldd->repGncFreq,
+                                         &ldd->ld.repayment_schedule,
+                                         ldd->ld.repStartDate);
 
         /* Set the 'from' accounts of the various options to be the
          * Assets-From account, if they're not already something else. */
@@ -1411,9 +1416,9 @@
                                      ldd->ld.repPriAcct );
         gnc_account_sel_set_account( ldd->repIntToGAS,
                                      ldd->ld.repIntAcct );
-        gnc_frequency_setup( ldd->repGncFreq,
-                             ldd->ld.repFreq,
-                             ldd->ld.repStartDate );
+        gnc_frequency_setup_recurrence(ldd->repGncFreq,
+                                       ldd->ld.repayment_schedule,
+                                       ldd->ld.repStartDate);
 }
 
 static
@@ -1477,7 +1482,7 @@
 
         gnc_account_sel_set_account( ldd->payAcctToGAS,   rod->to );
 
-        uniq = (rod->fs != NULL);
+        uniq = (rod->schedule != NULL);
         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqPartRb),
                                       !uniq );
         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqUniqRb),
@@ -1485,8 +1490,7 @@
         gtk_widget_set_sensitive( GTK_WIDGET(ldd->payFreqAlign),
                                   uniq );
         if ( uniq ) {
-                gnc_frequency_setup( ldd->payGncFreq,
-                                     rod->fs, rod->startDate );
+                gnc_frequency_setup_recurrence( ldd->payGncFreq, rod->schedule, rod->startDate );
         }
 
         g_string_free( str, TRUE );
@@ -1548,22 +1552,20 @@
          */
 
         /* neither of these should happen. */
-        g_assert( ! (rod->fs && !rod->startDate) );
-        g_assert( ! (!rod->fs && rod->startDate) );
+        g_assert( ! (rod->schedule && !rod->startDate) );
+        g_assert( ! (!rod->schedule && rod->startDate) );
 
         if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ldd->payTxnFreqUniqRb)) ) {
-                if ( rod->fs == NULL ) {
-                        rod->fs = xaccFreqSpecMalloc( gnc_get_current_book() );
-                }
                 if ( rod->startDate == NULL ) {
                         rod->startDate = g_date_new();
                 }
-                gnc_frequency_save_state( ldd->payGncFreq,
-                                          rod->fs, rod->startDate );
+                recurrenceListFree(&rod->schedule);
+                gnc_frequency_save_to_recurrence(ldd->payGncFreq,
+                                                 &rod->schedule,
+                                                 rod->startDate);
         } else {
-                if ( rod->fs ) {
-                        xaccFreqSpecFree( rod->fs );
-                        rod->fs = NULL;
+                if (rod->schedule) {
+                        recurrenceListFree(&rod->schedule);
                 }
                 if ( rod->startDate ) {
                         g_date_free( rod->startDate );
@@ -1655,17 +1657,18 @@
                 RepayOptData *rod;
                 rod = ldd->ld.repayOpts[ ldd->currentIdx ];
 
-                if ( rod->fs == NULL ) {
-                        rod->fs = xaccFreqSpecMalloc( gnc_get_current_book() );
-                        xaccFreqSpecSetMonthly( rod->fs, ldd->ld.startDate, 1 );
-                        xaccFreqSpecSetUIType( rod->fs, UIFREQ_MONTHLY );
+                if ( rod->schedule == NULL ) {
+                        Recurrence *r = g_new0(Recurrence, 1);
+                        recurrenceSet(r, 1, PERIOD_MONTH, ldd->ld.startDate);
+                        rod->schedule = g_list_append(rod->schedule, r);
                 }
                 if ( rod->startDate == NULL ) {
                         rod->startDate = g_date_new();
                         *rod->startDate = *ldd->ld.startDate;
                 }
-                gnc_frequency_setup( ldd->payGncFreq,
-                                     rod->fs, rod->startDate );
+                gnc_frequency_setup_recurrence(ldd->payGncFreq,
+                                               rod->schedule,
+                                               rod->startDate);
         }
 }
 
@@ -1898,51 +1901,28 @@
 
 }
 
-#if 0
-static
-void
-ld_gnc_ttinfo_free( gpointer data, gpointer ud )
+static int
+ld_calc_sx_instance_num(GDate *start_date, GList *schedule)
 {
-        gnc_ttinfo_free( (TTInfo*)data );
-}
-#endif
+    int instance_count;
+    GDate next_date, today;
 
-static
-int
-ld_calc_current_instance_num( int monthsPassed, FreqSpec *fs )
-{
-        float mult = 1.0;
-        UIFreqType uift;
-        uift = xaccFreqSpecGetUIType( fs );
-        switch ( uift ) {
-        case UIFREQ_WEEKLY:
-        {
-                int wMult, dow;
-                xaccFreqSpecGetWeekly( fs, &wMult, &dow );
-                mult = (4.0 / wMult);
-        }
-        break;
-        case UIFREQ_BI_WEEKLY:
-        case UIFREQ_SEMI_MONTHLY:
-                mult = 2.0;
-                break;
-        case UIFREQ_MONTHLY:
-        case UIFREQ_QUARTERLY:
-        case UIFREQ_TRI_ANUALLY:
-        case UIFREQ_SEMI_YEARLY:
-        case UIFREQ_YEARLY:
-        {
-                int mMult, dom, offset;
-                xaccFreqSpecGetMonthly( fs, &mMult, &dom, &offset );
-                mult = ( 1.0 / mMult );
-        }
-        break;
-        default:
-                PERR( "Wacky loan repayment frequency [%d]", uift );
-                break;
-        }
+    g_date_clear(&next_date, 1);
+    g_date_clear(&today, 1);
+    g_date_set_time_t(&today, time(NULL));
 
-        return floor( monthsPassed * mult );
+    if (g_date_compare(start_date, &today) > 0)
+        return 0;
+
+    instance_count = -1;
+    do
+    {
+        instance_count++;
+        recurrenceListNextInstance(schedule, start_date, &next_date);
+    }
+    while (g_date_compare(&next_date, &today) < 0);
+
+    return instance_count;
 }
 
 static
@@ -1986,7 +1966,7 @@
 
         sx = xaccSchedXactionMalloc( gnc_get_current_book() );
         xaccSchedXactionSetName( sx, tcSX->name );
-        xaccSchedXactionSetFreqSpec( sx, tcSX->freq );
+        gnc_sx_set_schedule(sx, tcSX->schedule);
         xaccSchedXactionSetStartDate( sx, &tcSX->start );
         xaccSchedXactionSetLastOccurDate( sx, &tcSX->last );
         xaccSchedXactionSetEndDate( sx, &tcSX->end );
@@ -2013,7 +1993,7 @@
 /**
  * Does the work to setup the given toCreateSX structure for a specific
  * repayment.  Note that if the RepayOptData doesn't specify a unique
- * FreqSpec, the paymentSX and the tcSX parameters will be the same.
+ * schedule, the paymentSX and the tcSX parameters will be the same.
  **/
 static
 void
@@ -2255,7 +2235,7 @@
 {
         /* The main loan-payment SX.*/
         toCreateSX *paymentSX = NULL;
-        /* A GList of any other repayment SXes with different FreqSpecs. */
+        /* A GList of any other repayment SXes with different schedule. */
         GList *repaySXes = NULL;
         /* The currently-being-referenced toCreateSX. */
         toCreateSX *tcSX;
@@ -2273,7 +2253,7 @@
                 paymentSX->end = *ldd->ld.repStartDate;
                 g_date_add_months( &paymentSX->end, ldd->ld.numMonRemain - 1);
         }
-        paymentSX->freq = ldd->ld.repFreq;
+        paymentSX->schedule = ldd->ld.repayment_schedule;
         /* Figure out the correct current instance-count for the txns in the
          * SX. */
         paymentSX->instNum =
@@ -2431,7 +2411,7 @@
                         continue;
 
                 tcSX = paymentSX;
-                if ( rod->fs != NULL ) {
+                if ( rod->schedule != NULL ) {
                         tcSX = g_new0( toCreateSX, 1 );
                         gstr = g_string_new( ldd->ld.repMemo );
                         g_string_append_printf( gstr, " - %s",
@@ -2443,13 +2423,13 @@
                                 tcSX->end = tcSX->last;
                                 g_date_add_months( &tcSX->end, ldd->ld.numMonRemain );
                         }
-                        tcSX->freq    = rod->fs;
+                        tcSX->schedule = rod->schedule;
                         /* So it won't get destroyed when the close the
                          * Druid. */
-                        tcSX->instNum = ld_calc_current_instance_num( paymentSX->instNum,
-                                                                      rod->fs );
-                        rod->fs       = NULL;
-                        tcSX->mainTxn   = gnc_ttinfo_malloc();
+                        tcSX->instNum =
+                            ld_calc_sx_instance_num(&tcSX->start, rod->schedule);
+                        rod->schedule = NULL;
+                        tcSX->mainTxn = gnc_ttinfo_malloc();
                         gnc_ttinfo_set_currency( tcSX->mainTxn,
                                                  gnc_default_currency() );
                         gnc_ttinfo_set_description( tcSX->mainTxn,
@@ -2641,20 +2621,21 @@
 {
         GDate start, end;
         gnc_numeric *rowNumData;
-        GHashTable *schedule;
+        GHashTable *repayment_schedule;
 
         g_date_clear( &start, 1 );
         g_date_clear( &end, 1 );
         ld_get_loan_range( ldd, &start, &end );
 
-        /* The schedule is a hash of GDates to row-of-gnc_numeric[N] data,
-         * where N is the number of columns as determined by the _prep
-         * function, and stored in LoanData::revNumPmts. */
-        schedule = g_hash_table_new( g_date_hash, g_date_equals );
+        /* The repayment_schedule is a hash of GDates to
+         * row-of-gnc_numeric[N] data, where N is the number of columns as
+         * determined by the _prep function, and stored in
+         * LoanData::revNumPmts. */
+        repayment_schedule = g_hash_table_new( g_date_hash, g_date_equals );
 
         /* Do the master repayment */
         {
-                GDate curDate;
+                GDate curDate, nextDate;
                 GString *pmtFormula, *ppmtFormula, *ipmtFormula;
                 int i;
                 GHashTable *ivar;
@@ -2670,20 +2651,21 @@
                 g_date_clear( &curDate, 1 );
                 curDate = start;
                 g_date_subtract_days( &curDate, 1 );
-                xaccFreqSpecGetNextInstance( ldd->ld.repFreq,
-                                             &curDate, &curDate );
+                g_date_clear(&nextDate, 1);
+                recurrenceListNextInstance(ldd->ld.repayment_schedule, &curDate, &nextDate);
                 for ( i=1;
-                      g_date_valid( &curDate )
-                      && g_date_compare( &curDate, &end ) <= 0 ;
+                      g_date_valid( &nextDate )
+                      && g_date_compare( &nextDate, &end ) <= 0 ;
                       i++,
-                      xaccFreqSpecGetNextInstance( ldd->ld.repFreq,
-                                                   &curDate, &curDate ) )
+                      curDate = nextDate,
+                      recurrenceListNextInstance(ldd->ld.repayment_schedule,
+                                                 &curDate, &nextDate))
                 {
                         gnc_numeric ival;
                         gnc_numeric val;
                         char *eloc;
                         rowNumData =
-                                (gnc_numeric*)g_hash_table_lookup( schedule,
+                                (gnc_numeric*)g_hash_table_lookup( repayment_schedule,
                                                                    &curDate );
                         if ( rowNumData == NULL) {
                                 int j;
@@ -2695,7 +2677,7 @@
                                 for ( j=0; j<ldd->ld.revNumPmts; j++ ) {
                                         rowNumData[j] = gnc_numeric_error( GNC_ERROR_ARG );
                                 }
-                                g_hash_table_insert( schedule,
+                                g_hash_table_insert( repayment_schedule,
                                                      (gpointer)dateKeyCopy,
                                                      (gpointer)rowNumData );
                         }
@@ -2740,32 +2722,35 @@
         /* Process any other enabled payments. */
         {
                 int i;
-                GDate curDate;
-                FreqSpec *fs;
+                GDate curDate, nextDate;
+                GList *schedule;
 
                 for ( i=0; i<ldd->ld.repayOptCount; i++ )
                 {
                         if ( ! ldd->ld.repayOpts[i]->enabled )
                                 continue;
 
-                        fs = ( ldd->ld.repayOpts[i]->fs != NULL
-                               ? ldd->ld.repayOpts[i]->fs
-                               : ldd->ld.repFreq );
+                        schedule
+                                = ( ldd->ld.repayOpts[i]->schedule != NULL
+                                    ? ldd->ld.repayOpts[i]->schedule
+                                    : ldd->ld.repayment_schedule );
 
                         g_date_clear( &curDate, 1 );
                         curDate = start;
                         g_date_subtract_days( &curDate, 1 );
-                        xaccFreqSpecGetNextInstance( fs, &curDate, &curDate );
-                        for ( ; g_date_valid( &curDate )
-                                && g_date_compare( &curDate, &end ) <= 0;
-                              xaccFreqSpecGetNextInstance(
-                                      fs, &curDate, &curDate ) )
+                        g_date_clear(&nextDate, 1);
+                        recurrenceListNextInstance(schedule, &curDate, &nextDate );
+                        for ( ; g_date_valid( &nextDate )
+                                && g_date_compare( &nextDate, &end ) <= 0;
+                              curDate = nextDate,
+                              recurrenceListNextInstance(
+                                      schedule, &curDate, &nextDate ) )
                         {
                                 gint gncn_how =
                                         GNC_DENOM_SIGFIGS(2)
                                         | GNC_RND_ROUND;
                                 gnc_numeric val;
-                                rowNumData = (gnc_numeric*)g_hash_table_lookup( schedule,
+                                rowNumData = (gnc_numeric*)g_hash_table_lookup( repayment_schedule,
                                                                                 &curDate );
                                 if ( rowNumData == NULL ) {
                                         int j;
@@ -2777,7 +2762,7 @@
                                         for ( j=0; j<ldd->ld.revNumPmts; j++ ) {
                                                 rowNumData[j] = gnc_numeric_error( GNC_ERROR_ARG );
                                         }
-                                        g_hash_table_insert( schedule,
+                                        g_hash_table_insert( repayment_schedule,
                                                              (gpointer)dateKeyCopy,
                                                              (gpointer)rowNumData );
                                 }
@@ -2801,11 +2786,11 @@
                         g_list_free( ldd->ld.revSchedule );
                         ldd->ld.revSchedule = NULL;
                 }
-                g_hash_table_foreach( schedule, ld_rev_hash_to_list,
+                g_hash_table_foreach( repayment_schedule, ld_rev_hash_to_list,
                                       &ldd->ld.revSchedule );
-                g_hash_table_foreach( schedule, ld_rev_hash_free_date_keys,
+                g_hash_table_foreach( repayment_schedule, ld_rev_hash_free_date_keys,
                                       NULL );
-                g_hash_table_destroy( schedule );
+                g_hash_table_destroy( repayment_schedule );
                 ldd->ld.revSchedule =
                         g_list_sort( ldd->ld.revSchedule, (GCompareFunc)g_date_compare );
         }



More information about the gnucash-changes mailing list