Merge branch 'test'
authorAlan J. Pippin <ajp@server.pippins.net>
Wed, 13 Feb 2008 15:44:32 +0000 (08:44 -0700)
committerAlan J. Pippin <ajp@pippins.net>
Wed, 13 Feb 2008 15:44:32 +0000 (08:44 -0700)
17 files changed:
bin/backup_phpgw_db
bin/import_ward_data
bin/merge_eq_ppi_eq_interview_tables [new file with mode: 0755]
bin/parse_ward_data
doc/install.txt
inc/class.eq.inc.php
inc/class.jscalendar.inc.php [new file with mode: 0644]
setup/db_config [new file with mode: 0644]
setup/eq_config [new file with mode: 0644]
setup/setup.inc.php
sql/eq.sql
templates/default/admin.tpl
templates/default/int_sched.tpl
templates/default/int_update.tpl
templates/default/ppi_sched.tpl
templates/default/ppi_update.tpl
templates/default/vis_sched.tpl

index b00afdabffcb0f04944482e548f46847bbae1923..beaf25488ca3f956947ff07e839d5db0d6313434 100755 (executable)
@@ -1,13 +1,14 @@
 #!/bin/bash
 
 MNTPNT="/backup"
+MOUNTIT=1
 DSTDIR="/backup/mysql/"
 DBNAME=phpgroupware
 DBUSER=phpgroupware
 DBPASS=phpgroupware
 
-mount -w -o remount $MNTPNT 
+[ $MOUNTIT == 1 ] && mount -w -o remount $MNTPNT 
 /usr/bin/mysqldump --databases $DBNAME -u $DBUSER --password=$DBPASS -c > $DSTDIR/mysql_phpgw_backup.sql
 ls -l $DSTDIR/mysql_phpgw_backup.sql
-mount -r -o remount $MNTPNT
+[ $MOUNTIT == 1 ] && mount -r -o remount $MNTPNT
 
index bd707b4da75f149659a18d4c63a6acc20481d66a..0e04f0598274506cec12fcc5de9760b36005d2a0 100755 (executable)
@@ -2,13 +2,12 @@
 
 use DBI;
 use Getopt::Std;
-###################################################
-# GLOBALS
-$dbname = "phpgroupware";
-$dbhost = "192.168.0.2";
-$dbport = 3306;
-$dbuser = "phpgroupware";
-$dbpass = "phpgroupware";
+
+$mydir = `cd \$(dirname $0) 2>/dev/null; pwd`; chomp($mydir);
+unshift @INC,("$mydir/../setup");
+if( -f "$mydir/../setup/db_config.local") { require "db_config.local"; }
+else { require "db_config"; }
+
 %hometeaching_data = ();
 %membership_data = ();
 getopts('vsn:o:');
@@ -664,7 +663,7 @@ sub check_for_changed_ids
 
 ###################################################
 # Open a connection to the database
-$dbh=DBI->connect("dbi:mysql:dbname=$dbname;host=$dbhost port=$dbport",$dbuser,$dbpass,{
+$dbh=DBI->connect("dbi:mysql:dbname=$dbname:host=$dbhost:port=$dbport",$dbuser,$dbpass,{
     AutoCommit=>0,
     PrintError=>0}) or print "Connect Failure:".$DBI::errstr."\n" and exit 2;
 
@@ -726,6 +725,8 @@ if($opt_s) { $dbh->disconnect(); exit; }
 &update_eq_parent_table();
 &update_eq_child_table();
 
+print "\n-> Import Successful! DONE...\n";
+
 ###################################################
 # Disconnect from the database
 $dbh->disconnect();
@@ -733,13 +734,3 @@ $dbh->disconnect();
 ######################################################################
 
 
-
-
-
-
-
-
-
-
-
-
diff --git a/bin/merge_eq_ppi_eq_interview_tables b/bin/merge_eq_ppi_eq_interview_tables
new file mode 100755 (executable)
index 0000000..cd7484b
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/perl
+
+use DBI;
+use Getopt::Std;
+
+$mydir = `cd \$(dirname $0) 2>/dev/null; pwd`; chomp($mydir);
+unshift @INC,("$mydir/../setup");
+if( -f "$mydir/../setup/db_config.local") { require "db_config.local"; }
+else { require "db_config"; }
+
+###################################################
+# Connect to the database
+$dbh=DBI->connect("dbi:mysql:dbname=$dbname:host=$dbhost:port=$dbport",$dbuser,$dbpass,{
+    AutoCommit=>0,
+    PrintError=>0}) or print "Connect Failure:".$DBI::errstr."\n" and exit 2;
+###################################################
+
+# Add a new 'aaronic' column to the eq_ppi table
+$sth = $dbh->prepare("ALTER TABLE `eq_ppi` ADD `aaronic` INT( 16 ) NOT NULL DEFAULT '0' AFTER `elder`");
+$sth->execute or die "-E- DB error: $DBI::errstr\n";
+
+# Parse the data out of the eq_interview table and add them to the eq_ppi table
+$sth = $dbh->prepare("select * from eq_interview");
+$sth->execute or die "-E- DB error: $DBI::errstr\n";
+while($row = $sth->fetchrow_hashref) {
+    $interviewer = $row->{interviewer};
+    $elder = $row->{elder};
+    $aaronic = $row->{aaronic};
+    $date = $row->{date};
+    $notes = $row->{notes};
+    $notes =~ s/\'/\\\'/g;
+    $eqpresppi = 0;
+    #print "$interviewer $elder $aaronic $date $eqpresppi $notes\n";
+    $sth2 = $dbh->prepare("insert into eq_ppi values (NULL,'$interviewer','$elder','$aaronic','$date','$notes','$eqpresppi')");
+    $sth2->execute or die "-E- DB error: $DBI::errstr\n";
+}
+
+print "\n-> Succesfully imported all eq_interview table entries into eq_ppi table...\n";
+print "-> You may drop the eq_interview table once you know all your data was transferred to the eq_ppi table correctly..\n";
+
+###################################################
+# Disconnect from the database
+$dbh->disconnect();
+###################################################
+
+
index 82a173038d774daa48abb8a312988a2a73c5bd77..e6d94fb4e1670239ce13538b8df23a1d62597a41 100755 (executable)
@@ -2,13 +2,12 @@
 
 use DBI;
 use Getopt::Std;
-###################################################
-# GLOBALS
-$dbname = "phpgroupware";
-$dbhost = "192.168.0.2";
-$dbport = 3306;
-$dbuser = "phpgroupware";
-$dbpass = "phpgroupware";
+
+$mydir = `cd \$(dirname $0) 2>/dev/null; pwd`; chomp($mydir);
+unshift @INC,("$mydir/../setup");
+if( -f "$mydir/../setup/db_config.local") { require "db_config.local"; }
+else { require "db_config"; }
+
 %hometeaching_data = ();
 %membership_data = ();
 getopts('vsn:o:b');
@@ -91,7 +90,7 @@ sub print_birthdays
 
 ###################################################
 # Open a connection to the database
-$dbh=DBI->connect("dbi:mysql:dbname=$dbname;host=$dbhost port=$dbport",$dbuser,$dbpass,{
+$dbh=DBI->connect("dbi:mysql:dbname=$dbname:host=$dbhost:port=$dbport",$dbuser,$dbpass,{
     AutoCommit=>0,
     PrintError=>0}) or print "Connect Failure:".$DBI::errstr."\n" and exit 2;
 
index c8c5d6b17f3e4bec34bbbd7f186627d36ea861c1..406126ed4872ebce2363d9e34a6ac741cb3bc493 100644 (file)
@@ -16,7 +16,7 @@ Downloading
    https://eq.pippins.net/eq.tar
 
    It can also be obtained via the GIT revision control system by pulling from here:
-   http://git.pippins.net/eq/
+   http://git.pippins.net/eq/.git
 
 Installing
 
@@ -29,16 +29,22 @@ Installing
       need to assign this app to the users you want to have be able to use it.
       Enable it for each user by going to Site Admin -> User Accounts -> <username> -> edit
       Make sure the "eq" application has a checkmark next to it under "Permissions this user has"
-   4) Edit the LOCAL CONFIGURATION section of eq/inc/class.eq.inc.php
-      Make sure you update the path locations for your specific:
-      upload_target_path & script_path
-   5) A graphical representation of the mysql schema used by this application can 
+   4) Copy the setup/db_config to setup/db_config.local and change the values in .local appropriately. 
+   5) Copy the setup/eq_config to setup/eq_config.local and change the values in .local appropriately.
+      Make sure you update the path locations for your specific installation locations: 
+      upload_target_path & application_path
+   6) Try to run eq/bin/import_ward_data & parse_ward_data scripts from the commandline
+      to check for any missing perl library dependencies and mysql connection. 
+      Just run them without command line args.
+      Install the right perl modules until the scripts run without any errors.
+   7) A graphical representation of the mysql schema used by this application can 
       be found here: eq/sql/eq.jpg
-   6) Click on the Admin tool in the EQ app to import your initial set of ward data
+   8) Click on the Admin tool in the EQ app to import your initial set of ward data
       obtained from MLS into the EQ application.
-   7) Click on the Admin tool and update the EQ Presidency Table appropriately.
+   9) Click on the Admin tool and update the EQ Presidency Table appropriately.
       The most important thing at this point is to get your district leaders added 
       for each district you have in your quorum.
+  10) I highly recommend installing phpmyadmin to view/edit/debug mysql tables related to this tool.
 
 Requirements
 
index 84f234f96c6068f71635bf79e25d48d62e218d66..4574d4b9290db9ecc5b22dad4605117b303ab943 100644 (file)
@@ -63,24 +63,20 @@ class eq
      'send_ical_appt' => True,
      'assign_view'    => True,
      'assign_update'  => True,
+     'get_time_selection_form' => True,
      );
  
   function eq()
     {
-      // LOCAL CONFIGURATION. PLEASE UPDATE AS APPROPRIATE.
-      $this->upload_target_path = "/home/users/eqpres/eq_data/";
-      $this->script_path = "/usr/share/phpgroupware/eq/bin/";
-      $this->default_ht_num_months = 3;
-      $this->default_ppi_num_months = 3;
-      $this->default_ppi_num_years = 0;
-      $this->default_int_num_quarters = 1;
-      $this->default_int_num_years = 0;
-      $this->default_att_num_quarters = 1;
-      $this->default_vis_num_years = 1;
-      $this->max_num_districts = 4;
+      if(file_exists('setup/eq_config.local')) {
+       include('setup/eq_config.local');
+      } else {
+       include('setup/eq_config');
+      }
+
+      $this->script_path = "$this->application_path"."/bin";
       $this->max_presidency_members = 99;
       $this->max_appointments = 32768;
-      // END LOCAL CONFIGURATION
       
       $this->db                = $GLOBALS['phpgw']->db;
       $this->db2       = $this->db;
@@ -91,7 +87,7 @@ class eq
       $this->grants     = $GLOBALS['phpgw']->acl->get_grants('eq');
       $this->grants[$this->account] = PHPGW_ACL_READ + PHPGW_ACL_ADD + PHPGW_ACL_EDIT + PHPGW_ACL_DELETE;
        
-      $this->jscal = CreateObject('phpgwapi.jscalendar');   // before phpgw_header() !!!
+      $this->jscal = CreateObject('eq.jscalendar');   // before phpgw_header() !!!
       $this->cal_options = 'daFormat    : "%Y-%m-%d",
                                 ifFormat    : "%Y-%m-%d",
                                 mondayFirst : false,
@@ -298,12 +294,24 @@ class eq
                $month_start = "$year"."-"."$month"."-"."01";
                $month_end = "$year"."-"."$month"."-"."31";
                $month = "$month"."/"."$year";
+               
                //print "m: $m month: $month year: $year month_start: $month_start month_end: $month_end<br>";
                // Add this to the query to filter on only visits made by this companionship:
                // " AND companionship=" . $unique_companionships[$j]['companionship'].
+
+               // First check to see if the currently assigned companionship has visited them
                $sql = "SELECT * FROM eq_visit WHERE date >= '$month_start' AND date <= '$month_end' ".
-                      " AND companionship!=0".
-                      " AND family=". $family_id;
+                  " AND companionship=".$unique_companionships[$j]['companionship'].
+                  " AND family=". $family_id;
+               $query_id = $this->db2->query($sql,__LINE__,__FILE__);
+               if($this->db2->num_rows($query_id) == 0) {
+                 // We did not find any visits made by the currently assigned companionship,
+                 // look for visits made by any other companionship other than 0. (0 == EQ Presidency Visit)
+                 $sql = "SELECT * FROM eq_visit WHERE date >= '$month_start' AND date <= '$month_end' ".
+                    " AND companionship!=0".
+                    " AND family=". $family_id;
+                 $query_id = $this->db2->query($sql,__LINE__,__FILE__);
+               }
                $this->db2->query($sql,__LINE__,__FILE__);
                $link_data['menuaction'] = 'eq.eq.ht_update';
                $link_data['date'] = $month_start;
@@ -404,16 +412,9 @@ class eq
            }
          for ($j=0; $j < count($unique_companionships); $j++)
            {
-             // FIXME: We won't be able to go back and edit history on families that have been
-             // reassigned to a different companionship. The following delete command will not delete
-             // the history of visits under an older companionship, only the ones for the existing
-             // companionship. This will lead to duplicate visits being entered for an older
-             // month for the same family, making it impossible to change the past history once
-             // a family is reassigned. However, you will be able to view the history just fine.
-
              //$comp=$unique_companionships[$j]['companionship'];
              //print "deleting from eq_visit where companionship=$comp and date=$date and district=$district<br>";
-             // Delete all the visits that have taken place for all families for this month
+             // Delete all the visits that have taken place for all families for this companionsthip for this month
              $this->db->query("DELETE from eq_visit where companionship=" . $unique_companionships[$j]['companionship'] .
                               " AND " . "date='" . $date . "'",__LINE__,__FILE__);
            }
@@ -518,10 +519,21 @@ class eq
            $table_data.="<tr bgcolor=". $this->t->get_var('tr_color') ."><td>$family_name Family</td>";
            
            $header_row="<th width=$comp_width><font size=-2>Families</th>";
+
+           // First check to see if the currently assigned companionship has visited them
            $sql = "SELECT * FROM eq_visit WHERE date >= '$month_start' AND date <= '$month_end' ".
+                  " AND companionship=".$unique_companionships[$j]['companionship'].
+                  " AND family=". $family_id;
+           $query_id = $this->db2->query($sql,__LINE__,__FILE__);
+           if($this->db2->num_rows($query_id) == 0) {
+             // We did not find any visits made by the currently assigned companionship,
+             // look for visits made by any other companionship other than 0. (0 == EQ Presidency Visit)
+             $sql = "SELECT * FROM eq_visit WHERE date >= '$month_start' AND date <= '$month_end' ".
                   " AND companionship!=0".
                   " AND family=". $family_id;
-           $this->db2->query($sql,__LINE__,__FILE__);
+             $query_id = $this->db2->query($sql,__LINE__,__FILE__);
+           }
+           
            $value = $family_id . "/" . $unique_companionships[$j]['companionship'] . "/" . $date;
            $header_row .= "<th width=$visit_width><font size=-2><a href=$link>$month</a></th>";
            if(!$total_visits) { $total_visits = 0; }
@@ -1389,26 +1401,28 @@ class eq
        {
          // Save any changes made to the appointment table
          $new_data = get_var('appt_notes',array('POST'));
-         foreach ($new_data as $entry)
-          {
-            $elder = $entry['elder'];
-            $appointment = $entry['appointment'];
-
-            //print "elder: $elder appointment: $appointment <br>";
-            
-            //Only perform a database update if we have made a change to this appointment
-            $sql = "SELECT * FROM eq_appointment where appointment='$appointment' and elder='$elder'";
-            $this->db->query($sql,__LINE__,__FILE__);
-            if(!$this->db->next_record()) {
-              // Perform database save actions here
-              $this->db->query("UPDATE eq_appointment set " .
-                               " elder='" . $elder . "'" .
-                               " WHERE appointment=" . $appointment,__LINE__,__FILE__);
-              // Email the appointment
-              $this->email_appt($appointment);
-            }
-
-          }
+         if($new_data != "") { 
+           foreach ($new_data as $entry)
+             {
+               $elder = $entry['elder'];
+               $appointment = $entry['appointment'];
+               
+               //print "elder: $elder appointment: $appointment <br>";
+               
+               //Only perform a database update if we have made a change to this appointment
+               $sql = "SELECT * FROM eq_appointment where appointment='$appointment' and elder='$elder'";
+               $this->db->query($sql,__LINE__,__FILE__);
+               if(!$this->db->next_record()) {
+                 // Perform database save actions here
+                 $this->db->query("UPDATE eq_appointment set " .
+                                  " elder='" . $elder . "'" .
+                                  " WHERE appointment=" . $appointment,__LINE__,__FILE__);
+                 // Email the appointment
+                 $this->email_appt($appointment);
+               }
+               
+             }
+         }
          
          // Save any changes made to the ppi notes table
          $new_data = get_var('ppi_notes',array('POST'));
@@ -1427,7 +1441,7 @@ class eq
           }
 
          $take_me_to_url = $GLOBALS['phpgw']->link('/eq/index.php','menuaction=eq.eq.ppi_sched');
-         Header('Location: ' . $take_me_to_url);
+         //Header('Location: ' . $take_me_to_url);
        }
 
       // Get the EQ President
@@ -1684,25 +1698,27 @@ class eq
        {
          // Save any changes made to the appointment table
          $new_data = get_var('appt_notes',array('POST'));
-         foreach ($new_data as $entry)
-          {
-            $elder = $entry['elder'];
-            $appointment = $entry['appointment'];
-
-            //print "elder: $elder appointment: $appointment <br>";
-            //Only perform a database update if we have made a change to this appointment
-            $sql = "SELECT * FROM eq_appointment where appointment='$appointment' and elder='$elder'";
-            $this->db->query($sql,__LINE__,__FILE__);
-            if(!$this->db->next_record()) {
-              // Perform database save actions here
-              $this->db->query("UPDATE eq_appointment set " .
-                               " elder='" . $elder . "'" .
-                               " WHERE appointment=" . $appointment,__LINE__,__FILE__);
-              
-              // Email the appointment
-              $this->email_appt($appointment);
-            }
-          }
+         if($new_data != "") { 
+           foreach ($new_data as $entry)
+             {
+               $elder = $entry['elder'];
+               $appointment = $entry['appointment'];
+               
+               //print "elder: $elder appointment: $appointment <br>";
+               //Only perform a database update if we have made a change to this appointment
+               $sql = "SELECT * FROM eq_appointment where appointment='$appointment' and elder='$elder'";
+               $this->db->query($sql,__LINE__,__FILE__);
+               if(!$this->db->next_record()) {
+                 // Perform database save actions here
+                 $this->db->query("UPDATE eq_appointment set " .
+                                  " elder='" . $elder . "'" .
+                                  " WHERE appointment=" . $appointment,__LINE__,__FILE__);
+                 
+                 // Email the appointment
+                 $this->email_appt($appointment);
+               }
+             }
+         }
          
          // Save any changes made to the int notes table
          $new_data = get_var('int_notes',array('POST'));
@@ -1725,7 +1741,7 @@ class eq
           }
 
          $take_me_to_url = $GLOBALS['phpgw']->link('/eq/index.php','menuaction=eq.eq.int_sched');
-         Header('Location: ' . $take_me_to_url);
+         //Header('Location: ' . $take_me_to_url);
        }
 
       // Get the Districts
@@ -1899,19 +1915,19 @@ class eq
              }
              
              // If this companionship has had a hometeaching interview this quarter, don't show them on the schedule list
-             $sql = "SELECT * FROM eq_interview WHERE date >= '$quarter_start' AND date < '$quarter_end' ".
+             $sql = "SELECT * FROM eq_ppi WHERE date >= '$quarter_start' AND date < '$quarter_end' ".
                 "AND elder=" . $id;
              $this->db2->query($sql,__LINE__,__FILE__);
              
              if(!$this->db2->next_record()) {
-               $sql = "SELECT * FROM eq_interview WHERE elder=" . $id . " ORDER BY date DESC";
+               $sql = "SELECT * FROM eq_ppi WHERE elder=" . $id . " ORDER BY date DESC";
                $this->db3->query($sql,__LINE__,__FILE__);
                if($this->db3->next_record()) { $date = $this->db3->f('date'); } else { $date = ""; }
                $link_data['menuaction'] = 'eq.eq.int_update';
                $link_data['elder'] = $id;
                $link_data['aaronic'] = 0;
                $link_data['name'] = $name;
-               $link_data['interview'] = '';
+               $link_data['ppi'] = '';
                $link_data['action'] = 'add';
                $link_data['interviewer'] = $districts[$d]['supervisor'];
                $link = $GLOBALS['phpgw']->link('/eq/index.php',$link_data);
@@ -1943,7 +1959,7 @@ class eq
                $link_data['elder'] = $this->db2->f('elder');
                $link_data['aaronic'] = $this->db2->f('aaronic');
                $link_data['name'] = $name;
-               $link_data['interview'] = $this->db2->f('int');
+               $link_data['ppi'] = $this->db2->f('ppi');
                $link_data['action'] = 'view';
                $link = $GLOBALS['phpgw']->link('/eq/index.php',$link_data);    
                $comps_with_quarterly_int++;
@@ -2036,25 +2052,27 @@ class eq
        {
          // Save any changes made to the appointment table
          $new_data = get_var('appt_notes',array('POST'));
-         foreach ($new_data as $entry)
-          {
-            $family = $entry['family'];
-            $appointment = $entry['appointment'];
-
-            //Only perform a database update if we have made a change to this appointment
-            $sql = "SELECT * FROM eq_appointment where appointment='$appointment' and family='$family'";
-            $this->db->query($sql,__LINE__,__FILE__);
-            if(!$this->db->next_record()) {
-
-              // Perform database save actions here
-              $this->db->query("UPDATE eq_appointment set " .
-                               " family='" . $family . "'" .
-                               " WHERE appointment=" . $appointment,__LINE__,__FILE__);
-              
-              // Email the appointment
-              $this->email_appt($appointment);
-            }
-          }
+         if($new_data != "") { 
+           foreach ($new_data as $entry)
+             {
+               $family = $entry['family'];
+               $appointment = $entry['appointment'];
+               
+               //Only perform a database update if we have made a change to this appointment
+               $sql = "SELECT * FROM eq_appointment where appointment='$appointment' and family='$family'";
+               $this->db->query($sql,__LINE__,__FILE__);
+               if(!$this->db->next_record()) {
+                 
+                 // Perform database save actions here
+                 $this->db->query("UPDATE eq_appointment set " .
+                                  " family='" . $family . "'" .
+                                  " WHERE appointment=" . $appointment,__LINE__,__FILE__);
+                 
+                 // Email the appointment
+                 $this->email_appt($appointment);
+               }
+             }
+         }
          
          // Save any changes made to the visit notes table
          $new_data = get_var('vis_notes',array('POST'));
@@ -2073,7 +2091,7 @@ class eq
           }
 
          $take_me_to_url = $GLOBALS['phpgw']->link('/eq/index.php','menuaction=eq.eq.vis_sched');
-         Header('Location: ' . $take_me_to_url);
+         //Header('Location: ' . $take_me_to_url);
        }
 
       // APPOINTMENT TABLE
@@ -2374,7 +2392,7 @@ class eq
          $year = date('Y') - $m;
          $year_start = $year - 1 . "-12-31"; $year_end = $year + 1 . "-01-01";
          $sql = "SELECT * FROM eq_ppi WHERE date > '$year_start' AND date < '$year_end' ".
-            "AND elder=" . $id;
+            "AND elder=" . $id . " AND eqpresppi=1";
          $this->db2->query($sql,__LINE__,__FILE__);
                  
          if(!$total_ppis[$m]) { $total_ppis[$m] = 0; }
@@ -2444,6 +2462,7 @@ class eq
       $interviewer_name = $this->db2->f('name');
       $this->t->set_var('interviewer',$interviewer . ' selected');
       $this->t->set_var('interviewer_name',$interviewer_name);
+      $this->t->set_var('eqpresppi_checked','');
       $this->t->fp('int_list','interviewer_list',True);
     
       if($action == 'save')
@@ -2453,6 +2472,7 @@ class eq
                           "   ppi='" . $ppi . "'" .
                    ", interviewer='" . $interviewer . "'" .
                          ", elder='" . $elder . "'" .
+                       ", aaronic='" . $aaronic . "'" .
                           ", date='" . $date . "'" .
                          ", notes='" . $notes . "'" .
                      ", eqpresppi='" . $eqpresppi . "'" .
@@ -2464,8 +2484,8 @@ class eq
       if($action == 'insert')
        {
          $notes = get_var('notes',array('POST'));
-         $this->db->query("INSERT INTO eq_ppi (interviewer,elder,date,notes,eqpresppi) "
-                          . "VALUES ('" . $interviewer . "','" . $elder . "','"
+         $this->db->query("INSERT INTO eq_ppi (interviewer,elder,aaronic,date,notes,eqpresppi) "
+                          . "VALUES ('" . $interviewer . "','" . $elder . "','" . $aaronic . "','"
                           . $date . "','" . $notes . "','" . $eqpresppi  ."')",__LINE__,__FILE__);
          $this->ppi_view();
          return false;
@@ -2481,6 +2501,7 @@ class eq
          $this->t->set_var('date','');
          $this->t->set_var('notes','');
          $this->t->set_var('eqpresppi',$eqpresppi);
+         $this->t->set_var('eqpresppi_checked','checked');
          $this->t->set_var('lang_done','Cancel');
          $this->t->set_var('lang_action','Adding New PPI');
          $this->t->set_var('actionurl',$GLOBALS['phpgw']->link('/eq/index.php','menuaction=eq.eq.ppi_update&ppi='
@@ -2499,6 +2520,7 @@ class eq
          $this->t->set_var('date',$this->db->f('date'));
          $this->t->set_var('notes',$this->db->f('notes'));
          $this->t->set_var('eqpresppi',$this->db->f('eqpresppi'));
+         if($this->db->f('eqpresppi') == 1) { $this->t->set_var('eqpresppi_checked','checked'); }
        }
       
       if($action == 'edit')
@@ -2652,7 +2674,7 @@ class eq
              $link_data['elder'] = $elder_id;
              $link_data['aaronic'] = $aaronic_id;
              $link_data['name'] = $name;
-             $link_data['interview'] = '';
+             $link_data['ppi'] = '';
              $link_data['action'] = 'add';
              $link = $GLOBALS['phpgw']->link('/eq/index.php',$link_data);
              $table_data.= "<tr bgcolor=". $this->t->get_var('tr_color') ."><td title=\"$phone\"><a href=$link>$name</a></td>";
@@ -2667,7 +2689,7 @@ class eq
                $month_start = "$year"."-"."$month"."-"."01";
                $month_end = "$year"."-"."$month"."-"."31";
                $month = "$month"."/"."$year";
-               $sql = "SELECT * FROM eq_interview WHERE date >= '$month_start' AND date <= '$month_end' ".
+               $sql = "SELECT * FROM eq_ppi WHERE date >= '$month_start' AND date <= '$month_end' ".
                   "AND elder=" . $elder_id . " AND aaronic=" . $aaronic_id;
                $this->db2->query($sql,__LINE__,__FILE__);
                $header_row .= "<th width=$int_width><font size=-2>$month</th>";
@@ -2683,7 +2705,7 @@ class eq
                  $link_data['elder'] = $elder_id;
                  $link_data['aaronic'] = $aaronic_id;
                  $link_data['name'] = $name;
-                 $link_data['interview'] = $this->db2->f('interview');
+                 $link_data['ppi'] = $this->db2->f('ppi');
                  $link_data['action'] = 'view';
                  $date = $this->db2->f('date');
                  $date_array = explode("-",$date);
@@ -2702,15 +2724,25 @@ class eq
        $total_companionships += $num_companionships;
        $stat_data = "<tr><td><b><font size=-2>$num_companionships Companionships<br>Interview Quarterly Totals:</font></b></td>";
 
-       for($m=$num_months; $m >=0; $m--) {
-         $month = $current_month - $m;
-         if(($month % 3) == 1) { $quarter_total = $ints[$m]; }
-         else { $quarter_total += $ints[$m]; }
-         $percent = ceil(($quarter_total / $num_companionships)*100);
-         $stat_data .= "<td align=center><font size=-2><b>$quarter_total<br>$percent%</font></b></td>";
+       // Print the hometeaching interview stats
+       if($this->monthly_hometeaching_interview_stats == 0) { //Quarterly
+         for($m=$num_months; $m >=0; $m--) {
+           $month = $current_month - $m;
+           if(($month % 3) == 1) { $quarter_total = $ints[$m]; }
+           else { $quarter_total += $ints[$m]; }
+           $percent = ceil(($quarter_total / $num_companionships)*100);
+           $stat_data .= "<td align=center><font size=-2><b>$quarter_total<br>$percent%</font></b></td>";
+         }
+         $stat_data .= "</tr>";
        }
-       $stat_data .= "</tr>";
-
+       else { // Monthly
+         for($m=$num_months; $m >=0; $m--) {
+           $percent = ceil(($ints[$m] / $num_companionships)*100);
+           $stat_data .= "<td align=center><font size=-2><b>$ints[$m]<br>$percent%</font></b></td>";
+         }
+         $stat_data .= "</tr>";
+       }
+       
        $this->t->set_var('table_width',$table_width);
        $this->t->set_var('header_row',$header_row);
        $this->t->set_var('table_data',$table_data);
@@ -2718,17 +2750,27 @@ class eq
        $this->t->fp('list','district_list',True);
       }
 
-      // Display the totals, cummulative per quarter
-      $quarter_total = 0;
-      $totals = "<tr><td><b><font size=-2>$total_companionships Total Comps<br>Interview Quarterly Totals:</font></b></td>";
-      for($m=$num_months; $m >=0; $m--) {
-       $month = $current_month - $m;
-       if(($month % 3) == 1) { $quarter_total = $total_ints[$m]; }
-       else { $quarter_total += $total_ints[$m]; }
-       $percent = ceil(($quarter_total / $total_companionships)*100);
-       $totals .= "<td align=center><font size=-2><b>$quarter_total<br>$percent%</font></b></td>";
+      // Display the totals
+      if($this->monthly_hometeaching_interview_stats == 0) { //Quarterly
+       $quarter_total = 0;
+       $totals = "<tr><td><b><font size=-2>$total_companionships Total Comps<br>Interview Quarterly Totals:</font></b></td>";
+       for($m=$num_months; $m >=0; $m--) {
+         $month = $current_month - $m;
+         if(($month % 3) == 1) { $quarter_total = $total_ints[$m]; }
+         else { $quarter_total += $total_ints[$m]; }
+         $percent = ceil(($quarter_total / $total_companionships)*100);
+         $totals .= "<td align=center><font size=-2><b>$quarter_total<br>$percent%</font></b></td>";
+       }
+       $totals .= "</tr>";
+      }
+      else { //Monthly
+       $totals = "<tr><td><b><font size=-2>$total_companionships Total Comps<br>Interview Monthly Totals:</font></b></td>";
+       for($m=$num_months; $m >=0; $m--) {
+         $percent = ceil(($total_ints[$m] / $total_companionships)*100);
+         $totals .= "<td align=center><font size=-2><b>$total_ints[$m]<br>$percent%</font></b></td>";
+       }
+       $totals .= "</tr>";
       }
-      $totals .= "</tr>";
       
       $this->t->set_var('totals',$totals);
       $this->t->pfp('out','int_view_t');
@@ -2745,16 +2787,18 @@ class eq
       $this->t->set_var('done_action',$GLOBALS['phpgw']->link('/eq/index.php','menuaction=eq.eq.int_view'));
       $this->t->set_var('readonly','');
       $this->t->set_var('disabled','');
+      $this->t->set_var('eqpresppi_checked','');
       
       $action = get_var('action',array('GET','POST'));
       $companionship = get_var('companionship',array('GET','POST'));
       $interviewer = get_var('interviewer',array('GET','POST'));      
       $name = get_var('name',array('GET','POST'));
-      $interview = get_var('interview',array('GET','POST'));
+      $ppi = get_var('ppi',array('GET','POST'));
       $elder = get_var('elder',array('GET','POST'));
       $aaronic = get_var('aaronic',array('GET','POST'));
       $date = get_var('date',array('GET','POST'));
       $notes = get_var('notes',array('GET','POST'));
+      $eqpresppi = get_var('eqpresppi',array('GET','POST'));
       
       $sql = "SELECT * FROM eq_district where valid=1 ORDER BY district ASC";
       $this->db->query($sql,__LINE__,__FILE__);
@@ -2778,14 +2822,15 @@ class eq
       if($action == 'save')
        {
          $notes = get_var('notes',array('POST'));
-         $this->db->query("UPDATE eq_interview set " .
-                    "   interview='" . $interview . "'" .
+         $this->db->query("UPDATE eq_ppi set " .
+                          "   ppi='" . $ppi . "'" .
                    ", interviewer='" . $interviewer . "'" .
                          ", elder='" . $elder . "'" .
                        ", aaronic='" . $aaronic . "'" .
                           ", date='" . $date . "'" .
                          ", notes='" . $notes . "'" .
-                          " WHERE interview=" . $interview,__LINE__,__FILE__);
+                     ", eqpresppi='" . $eqpresppi . "'" .
+                          " WHERE ppi=" . $ppi,__LINE__,__FILE__);
          $this->int_view();
          return false;
        }
@@ -2793,9 +2838,9 @@ class eq
       if($action == 'insert')
        {
          $notes = get_var('notes',array('POST'));
-         $this->db->query("INSERT INTO eq_interview (interviewer,elder,aaronic,date,notes) "
+         $this->db->query("INSERT INTO eq_ppi (interviewer,elder,aaronic,date,notes,eqpresppi) "
                           . "VALUES ('" . $interviewer . "','" . $elder . "','" . $aaronic . "','"
-                          . $date . "','" . $notes ."')",__LINE__,__FILE__);
+                          . $date . "','" . $notes ."','" . $eqpresppi . "')",__LINE__,__FILE__);
          $this->int_view();
          return false;
        }
@@ -2803,7 +2848,7 @@ class eq
       if($action == 'add')
        {
          $this->t->set_var('cal_date',$this->jscal->input('date','','','','','','',$this->cal_options));
-         $this->t->set_var('interview', '');
+         $this->t->set_var('ppi', '');
          $this->t->set_var('interviewer', $interviewer);
          $this->t->set_var('name',$name);
          $this->t->set_var('elder',$elder);
@@ -2812,22 +2857,23 @@ class eq
          $this->t->set_var('notes','');
          $this->t->set_var('lang_done','Cancel');
          $this->t->set_var('lang_action','Adding New Interview');
-         $this->t->set_var('actionurl',$GLOBALS['phpgw']->link('/eq/index.php','menuaction=eq.eq.int_update&interview='
-                                                               . $interview . '&action=' . 'insert'));
+         $this->t->set_var('actionurl',$GLOBALS['phpgw']->link('/eq/index.php','menuaction=eq.eq.int_update&ppi='
+                                                               . $ppi . '&action=' . 'insert'));
        }
 
       if($action == 'edit' || $action == 'view')
        {
-         $sql = "SELECT * FROM eq_interview WHERE interview=".$interview;
+         $sql = "SELECT * FROM eq_ppi WHERE ppi=".$ppi;
          $this->db->query($sql,__LINE__,__FILE__);
          $this->db->next_record();
-         $this->t->set_var('interview',$interview);
+         $this->t->set_var('ppi',$ppi);
          $this->t->set_var('name',$name);
          $this->t->set_var('interviewer', $this->db->f('interviewer'));
          $this->t->set_var('elder',$this->db->f('elder'));
          $this->t->set_var('aaronic',$this->db->f('aaronic'));
          $this->t->set_var('date',$this->db->f('date'));
          $this->t->set_var('notes',$this->db->f('notes'));
+         if($this->db->f('eqpresppi') == 1) { $this->t->set_var('eqpresppi_checked','checked'); }
        }
       
       if($action == 'edit')
@@ -2835,8 +2881,8 @@ class eq
          $this->t->set_var('cal_date',$this->jscal->input('date',$date,'','','','','',$this->cal_options));
          $this->t->set_var('lang_done','Cancel');
          $this->t->set_var('lang_action','Editing Interview');
-         $this->t->set_var('actionurl',$GLOBALS['phpgw']->link('/eq/index.php','menuaction=eq.eq.int_update&interview='
-                                                               . $interview . '&action=' . 'save'));
+         $this->t->set_var('actionurl',$GLOBALS['phpgw']->link('/eq/index.php','menuaction=eq.eq.int_update&ppi='
+                                                               . $ppi . '&action=' . 'save'));
        }
 
       if($action == 'view')
@@ -2847,8 +2893,8 @@ class eq
          $this->t->set_var('disabled','DISABLED');
          $this->t->set_var('lang_done','Done');
          $this->t->set_var('lang_action','Viewing Interview');
-         $this->t->set_var('actionurl',$GLOBALS['phpgw']->link('/eq/index.php','menuaction=eq.eq.int_update&interview='
-                                                               . $interview . '&action=' . 'edit'));
+         $this->t->set_var('actionurl',$GLOBALS['phpgw']->link('/eq/index.php','menuaction=eq.eq.int_update&ppi='
+                                                               . $ppi . '&action=' . 'edit'));
        }
       
       $this->t->set_var('lang_reset','Clear Form');
@@ -3607,7 +3653,7 @@ class eq
           }
          
          $take_me_to_url = $GLOBALS['phpgw']->link('/eq/index.php','menuaction=eq.eq.schedule');
-         Header('Location: ' . $take_me_to_url);
+         //Header('Location: ' . $take_me_to_url);
        }
 
       $sql = "SELECT * FROM eq_presidency where valid=1";
@@ -3684,24 +3730,7 @@ class eq
            
            // Hour & Minutes selection
            $table_data.= "<td align=center>";
-           $table_data.= '<select name=sched['.$presidency.']['.$appointment.'][hour]>';
-           foreach(range(1,12) as $num) {
-             if($hour == $num) { $selected[$num] = 'selected="selected"'; } else { $selected[$num] = ''; }
-             $table_data.= '<option value='.$num.' '.$selected[$num].'>'.$num.'</option>';
-           }
-           $table_data.= '</select>';
-           $table_data.= '&nbsp;:&nbsp;';
-           $table_data.= '<select name=sched['.$presidency.']['.$appointment.'][minute]>';
-           foreach(range(0,3) as $num) {
-             $num = $num * 15; if($num == 0) { $num = "00"; }
-             if($minute == $num) { $selected[$num] = 'selected="selected"'; } else { $selected[$num] = ''; }
-             $table_data.= '<option value='.$num.' '.$selected[$num].'>'.$num.'</option>';
-           }
-           $table_data.= '</select>';
-           $table_data.= '<select name=sched['.$presidency.']['.$appointment.'][pm]>';
-           if($pm == 0) { $table_data.= '<option value=0 selected>am</option>'; $table_data.= '<option value=1>pm</option>'; }
-           else { $table_data.= '<option value=0>am</option>'; $table_data.= '<option value=1 selected>pm</option>'; }
-           $table_data.= '</select>';
+           $table_data .= $this->get_time_selection_form($hour, $minute, $pm, $presidency, $appointment);
            $table_data.= "</td>";
            
            // Elder drop down list (for PPIs)
@@ -3746,25 +3775,7 @@ class eq
        
          // Time selection
          $table_data.= "<td align=center>";
-         $table_data.= '<select name=sched['.$presidency.']['.$appointment.'][hour]>';
-         $table_data.= '<option value=""></option>';
-         foreach(range(1,12) as $num) {
-           $table_data.= '<option value='.$num.' '.$selected[$num].'>'.$num.'</option>';
-         }
-         $table_data.= '</select>';
-         $table_data.= '&nbsp;:&nbsp;';
-         $table_data.= '<select name=sched['.$presidency.']['.$appointment.'][minute]>';
-         $table_data.= '<option value=""></option>';
-         foreach(range(0,3) as $num) {
-           $num = $num * 15; if($num == 0) { $num = "00"; }
-           $table_data.= '<option value='.$num.'>'.$num.'</option>';
-         }
-         $table_data.= '</select>';
-         $table_data.= '<select name=sched['.$presidency.']['.$appointment.'][pm]>';
-         $table_data.= '<option value=""></option>';
-         $table_data.= '<option value=0>am</option>';
-         $table_data.= '<option value=1>pm</option>';
-         $table_data.= '</select>';
+         $table_data .= $this->get_time_selection_form(0, 0, 0, $presidency, $appointment);
          $table_data.= "</td>";
          
          // Elder drop down list
@@ -3834,13 +3845,21 @@ class eq
 
       if($action == 'upload')
        {        
-         $target_path = $this->upload_target_path . basename( $_FILES['uploadedfile']['name']);
+         $target_path = $this->upload_target_path . '/' . basename( $_FILES['uploadedfile']['name']);
          
-         if((($_FILES['uploadedfile']['type'] == "application/zip") ||
-             ($_FILES['uploadedfile']['type'] == "application/x-zip-compressed") ||
-             ($_FILES['uploadedfile']['type'] == "application/x-zip") ||
-             ($_FILES['uploadedfile']['type'] == "application/octet-stream")) &&
-            (move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path))) {
+         if(($_FILES['uploadedfile']['type'] == "application/zip") ||
+            ($_FILES['uploadedfile']['type'] == "application/x-zip-compressed") ||
+            ($_FILES['uploadedfile']['type'] == "application/x-zip") ||
+            ($_FILES['uploadedfile']['type'] == "application/octet-stream")) {
+
+           if(!move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
+             $uploadstatus = "<b><font color=red> -E- Unable to move the uploaded file to ";
+             $uploadstatus.= "the target path (check the path and permissions) of: $target_path</font></b>";
+             $this->t->set_var('uploadstatus',$uploadstatus);
+             $this->t->pfp('uploadhandle','upload',True);
+             return 0;
+           }
+           
            $uploadstatus = "<b>The following file was uploaded successfully: </b><br><br>";
            $uploadstatus.= "Filename : " . $_FILES['uploadedfile']['name'] . "<br>";
            $uploadstatus.= "Type     : " . $_FILES['uploadedfile']['type'] . "<br>";
@@ -3852,9 +3871,9 @@ class eq
            
            # make a directory for this data to be stored in
            $date="data_" . date("Y_m_d");
-           $data_dir = $this->upload_target_path . $date;
+           $data_dir = $this->upload_target_path . '/' . $date;
            print "-> Making the data directory: $date<br>\n";
-           exec('mkdir ' . $data_dir . ' 2>&1', $result, $return_code);
+           exec('mkdir -p ' . $data_dir . ' 2>&1', $result, $return_code);
            if($return_code != 0) {
              print implode('\n',$result) . "<br>";
              print "<b><font color=red>";
@@ -3876,12 +3895,11 @@ class eq
            
            # unzip the data into this directory
            print "-> Unzipping the data<br>\n";
-           $data_file = $data_dir . '';
-           exec('unzip ' . $data_dir . '/*.zip -d ' . $data_dir . ' 2>&1', $result, $return_code);
+           exec($this->unzip_path .' -u '. $data_dir . '/*.zip -d ' . $data_dir . ' 2>&1', $result, $return_code);
            if($return_code != 0) {
              print implode('\n',$result) . "<br>";
              print "<b><font color=red>";
-             print "-E- Unable to unzip the uploaded file into the data dir. Aborting import.";
+             print "-E- Unable to unzip the uploaded file into the data dir: $data_dir. Aborting import.";
              print "</font></b>";
              return 0;
            }
@@ -3889,7 +3907,7 @@ class eq
 
            # update the data_latest link to point to this new directory
            print "-> Updating the latest data dir link<br>\n";
-           $data_latest = $this->upload_target_path . 'data_latest';
+           $data_latest = $this->upload_target_path . '/data_latest';
            exec('rm ' . $data_latest. '; ln -s ' . $data_dir .' '. $data_latest .' 2>&1', $result, $return_code);
            if($return_code != 0) {
              print implode('\n',$result) . "<br>";
@@ -3905,8 +3923,8 @@ class eq
            ob_flush(); flush(); sleep(1);
            $import_log = $this->upload_target_path . '/import.log';
            $data_log = $this->upload_target_path . '/data.log';
-           $import_cmd = $this->script_path . 'import_ward_data ' . $data_latest . ' | tee ' . $import_log;
-           $parse_cmd = $this->script_path . 'parse_ward_data -v ' . $data_latest . ' > ' . $data_log;
+           $import_cmd = $this->script_path . '/import_ward_data ' . $data_latest . ' 2>&1 | tee ' . $import_log;
+           $parse_cmd = $this->script_path . '/parse_ward_data -v ' . $data_latest . ' > ' . $data_log . '2>&1';
            #print "import_cmd: $import_cmd<br>";
            #print "parse_cmd: $parse_cmd<br>";
            ob_start('ob_logstdout', 2);
@@ -4203,6 +4221,7 @@ class eq
          // Format the appointment time into an iCal UTC equivalent
          $dtstamp = gmdate("Ymd"."\T"."His"."\Z");
          $dtstart = gmdate("Ymd"."\T"."His"."\Z", mktime($hour,$minute,$seconds,$month,$day,$year));
+         $dtstartstr = date("l, F d, o g:i A", mktime($hour,$minute,$seconds,$month,$day,$year));
          
          // Set the email address of the person making the appointment
          $from = $GLOBALS['phpgw_info']['user']['fullname'] . "<" .
@@ -4223,7 +4242,7 @@ class eq
              $phone = $this->db2->f('phone');
              $appt_name = $elder_name . " Interview";
              $location = "$interviewer"."'s home";
-             $duration = 1800; // 30 minutes
+             $duration = $this->default_ppi_appt_duration * 60;
            }
          }
 
@@ -4245,11 +4264,13 @@ class eq
              if($this->db3->next_record()) {
                $location=$this->db3->f('address');
              }
-             $duration = 2700; // 45 minutes
+             $duration = $this->default_visit_appt_duration * 60;
            }
          }
 
          $dtend = gmdate("Ymd"."\T"."His"."\Z", mktime($hour,$minute,$seconds+$duration,$month,$day,$year));
+         $dtendstr = date("g:i A", mktime($hour,$minute,$seconds+$duration,$month,$day,$year));
+         $date = $dtstartstr . "-" . $dtendstr;
          $description = "$appt_name : $phone";
          
          if(($uid == 0) && ($appt_name != "")) { 
@@ -4265,7 +4286,7 @@ class eq
 
            $action = "PUBLISH";
            $this->send_ical_appt($action, $email, $from, $subject, $dtstamp, $dtstart,
-                                 $dtend, $location, $appt_name, $description, $uid);
+                                 $dtend, $date, $location, $appt_name, $description, $uid);
            
          } else if(($uid != 0) && ($appt_name == "")) {
            // Remove the calendar item for this appointment since it has already been sent
@@ -4279,7 +4300,7 @@ class eq
            
            $action = "CANCEL";
            $this->send_ical_appt($action, $email, $from, $subject, $dtstamp, $dtstart,
-                                 $dtend, $location, $appt_name, $description, $uid);
+                                 $dtend, $date, $location, $subject, $subject, $uid);
            
          } else if($uid != 0) {
            // Update the existing appointment since we have changed it
@@ -4288,7 +4309,7 @@ class eq
            $subject = "Canceled: $appt_date $appt_time";
            $action = "CANCEL";
            $this->send_ical_appt($action, $email, $from, $subject, $dtstamp, $dtstart,
-                                 $dtend, $location, $appt_name, $description, $uid);
+                                 $dtend, $date, $location, $subject, $subject, $uid);
            
            $uid = rand() . rand(); // Generate a random identifier for this appointment
            $this->db->query("UPDATE eq_appointment set" .
@@ -4298,7 +4319,7 @@ class eq
            $subject = "Updated: $appt_name";       
            $action = "PUBLISH";
            $this->send_ical_appt($action, $email, $from, $subject, $dtstamp, $dtstart,
-                                 $dtend, $location, $appt_name, $description, $uid);
+                                 $dtend, $date, $location, $appt_name, $description, $uid);
          }
          
        }
@@ -4306,16 +4327,36 @@ class eq
       return true;
     }
 
-  function send_ical_appt($action, $to, $from, $subject, $dtstamp, $dtstart, $dtend, $location, $summary, $description, $uid)
+  function send_ical_appt($action, $to, $from, $subject, $dtstamp, $dtstart, $dtend, $date, $location, $summary, $description, $uid)
     {
-      $headers = 'From: ' . "$from" . "\n" .
-        'Reply-To: ' . "$from" . "\n" .
-        'X-Mailer: PHP/' . phpversion() . "\n" .
-        'Content-Type: text/calendar;' . "\n" .
-        'Content-Transfer-Encoding: 7bit' . "\n";
-      
-      //$message = "phone: $phone date: $date time: $time";
-      $message ="";
+      // Initialize our local variables
+      $boundary = "=MIME_APPOINTMENT_BOUNDARY";
+      $message = "";
+      $headers = "";
+
+      // Form the headers for the email message
+      $headers.="X-Mailer: PHP/" . phpversion() . "\n";
+      $headers.="Mime-Version: 1.0\n";
+      $headers.="Content-Type: multipart/mixed; boundary=\"$boundary\"\n";
+      $headers.="Content-Disposition: inline\n";
+      $headers.="Reply-To: $from\n";
+      $headers.="From: $from\n";
+
+      // Print the plaintext version of the appointment
+      $message.="--$boundary\n";
+      $message.="Content-Type: text/plain; charset=us-ascii\n";
+      $message.="Content-Disposition: inline\n";
+      $message.="\n";
+      $message.="What: $description\n";
+      $message.="When: $date\n";
+      $message.="Where: $location\n";
+      $message.="\n";
+      
+      // Print the .ics attachment version of the appointment
+      $message.="--$boundary\n";
+      $message.="Content-Type: text/calendar; charset=us-ascii\n";
+      $message.="Content-Disposition: attachment; filename=\"appointment.ics\"\n";
+      $message.="\n";
       $message.="BEGIN:VCALENDAR" . "\n";
       $message.="VERSION:2.0" . "\n";
       $message.="PRODID:-//Microsoft Corporation//Outlook 11.0 MIMEDIR//EN" . "\n";
@@ -4334,10 +4375,65 @@ class eq
       $message.="CLASS:PUBLIC" . "\n";
       $message.="END:VEVENT" . "\n";
       $message.="END:VCALENDAR" . "\n";
-      
+
+      // Complete the message
+      $message.="--$boundary\n";
+
+      // Send the message
       mail($to, $subject, $message, $headers);
       
     }
+
+  function get_time_selection_form($hour, $minute, $pm, $presidency, $appointment)
+    {
+      $form_data = "";
+      $blank = 0;
+      
+      if($hour == 0) { $blank = 1; }
+
+      if($this->time_drop_down_lists == 1) {
+       // Create drop down lists to get the time
+       $form_data.= '<select name=sched['.$presidency.']['.$appointment.'][hour]>';
+       if($blank == 1) { $form_data.= '<option value=""></option>'; }
+       foreach(range(1,12) as $num) {
+         if($hour == $num) { $selected = 'selected="selected"'; } else { $selected = ''; }
+         $form_data.= '<option value='.$num.' '.$selected.'>'.$num.'</option>';
+       }
+       $form_data.= '</select>';
+       $form_data.= '&nbsp;:&nbsp;';
+       $form_data.= '<select name=sched['.$presidency.']['.$appointment.'][minute]>';
+       if($blank == 1) { $form_data.= '<option value=""></option>'; }
+       $num = 0;
+       while($num < 60) {
+         if($num < 10) { $num = "0" . "$num"; }
+         if($minute == $num) { $selected = 'selected="selected"'; } else { $selected = ''; }
+         if($blank == 1) { $selected = ""; }
+         $form_data.= '<option value='.$num.' '.$selected.'>'.$num.'</option>';
+         $num = $num + $this->time_drop_down_list_inc;
+       }
+       $form_data.= '</select>';
+      } else {
+       // Use free form text fields to get the time
+       if($blank == 1) { $hour = ""; $minute = ""; $ampm = ""; }
+       $form_data.= '<input type=text size=2 name=sched['.$presidency.']['.$appointment.'][hour] value='.$hour.'>';
+       $form_data.= ':';
+       $form_data.= '<input type=text size=2 name=sched['.$presidency.']['.$appointment.'][minute] value='.$minute.'>';
+       $form_data.= '&nbsp;';
+      }
+      // Always use a drop-down select form for am/pm
+      $form_data.= '<select name=sched['.$presidency.']['.$appointment.'][pm]>';
+      if($blank == 0) { 
+       if($pm == 0) { $form_data.= '<option value=0 selected>am</option>'; $form_data.= '<option value=1>pm</option>'; }
+       if($pm == 1) { $form_data.= '<option value=0>am</option>'; $form_data.= '<option value=1 selected>pm</option>'; }
+      } else {
+       $form_data.= '<option value=""></option>';
+       $form_data.= '<option value=0>am</option>';
+       $form_data.= '<option value=1>pm</option>';
+      }
+      $form_data.= '</select>';
+      
+      return $form_data;
+    }
 }
 
 ?>
diff --git a/inc/class.jscalendar.inc.php b/inc/class.jscalendar.inc.php
new file mode 100644 (file)
index 0000000..0fda175
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+       /**
+       * jsCalendar wrapper-class
+       *
+       * @author Ralf Becker <RalfBecker@outdoor-training.de>
+       * @copyright Copyright (C) 2003,2004 Free Software Foundation, Inc. http://www.fsf.org/
+       * @license http://www.fsf.org/licenses/gpl.html GNU General Public License
+       * @package phpgwapi
+       * @subpackage gui
+       * @version $Id: class.jscalendar.inc.php,v 1.1.2.12 2004/05/01 09:24:53 skwashd Exp $
+       */
+
+       /**
+       * jsCalendar wrapper-class
+       *
+       * @package phpgwapi
+       * @subpackage gui
+       * @internal The constructor load the necessary javascript-files
+       */
+class jscalendar
+{
+       /*!
+       @function jscalendar
+       @syntax jscalendar( $do_header=True )
+       @author ralfbecker
+       @abstract constructor of the class
+       @param $do_header if true, necessary javascript and css gets loaded, only needed for input
+       */
+       function jscalendar($do_header=True)
+       {
+               if(!is_object($GLOBALS['phpgw']->js))
+               {
+                       $GLOBALS['phpgw']->js = createObject('phpgwapi.javascript');
+               }
+               $GLOBALS['phpgw']->js->validate_file('jscalendar', 'calendar');
+               $this->phpgw_js_url = $GLOBALS['phpgw_info']['server']['webserver_url'].'/phpgwapi/js';
+               $this->dateformat = $GLOBALS['phpgw_info']['user']['preferences']['common']['dateformat'];
+
+               if ($do_header && !strstr($GLOBALS['phpgw_info']['flags']['css'],'jscalendar'))
+               {
+                       $GLOBALS['phpgw_info']['flags']['css'] .= "-->\n</style>\n"
+                               . '<link rel="stylesheet" type="text/css" media="all" href="'
+                               . $this->phpgw_js_url
+                               . '/jscalendar/calendar-win2k-cold-1.css" title="win2k-cold-1" />'
+                               . "\n<style type=\"text/css\">\n<!--\n";
+
+                       $GLOBALS['phpgw_info']['flags']['java_script'] .= "\n"
+                               . '<script type="text/javascript" src="'
+                               . $GLOBALS['phpgw']->link('/phpgwapi/js/jscalendar/jscalendar-setup.php')
+                               ."\">\n</script>\n";
+               }
+       }
+
+       /*!
+       @function input
+       @syntax input( $name,$date,$year=0,$month=0,$day=0 )
+       @author ralfbecker
+       @abstract creates an inputfield for the jscalendar (returns the necessary html and js)
+       @param $name name and id of the input-field (it also names the id of the img $name.'-toggle')
+       @param $date date as string or unix timestamp (in users localtime)
+       @param $year,$month,$day if $date is not used
+       @param $helpmsg a helpmessage for the statusline of the browser
+       @param $options any other options to the inputfield
+       @param $setup any other calendar setup options
+       */
+       function input($name,$date,$year=0,$month=0,$day=0,$helpmsg='',$options='',$setup='')
+       {
+               //echo "<p>jscalendar::input(name='$name', date='$date'='".date('Y-m-d',$date)."', year='$year', month='$month', day='$day')</p>\n";
+
+               if ($date && (is_int($date) || is_numeric($date)))
+               {
+                       $year  = intval($GLOBALS['phpgw']->common->show_date($date,'Y'));
+                       $month = intval($GLOBALS['phpgw']->common->show_date($date,'n'));
+                       $day   = intval($GLOBALS['phpgw']->common->show_date($date,'d'));
+               }
+               if ($year && $month && $day)
+               {
+                       $date = date($this->dateformat,mktime(12,0,0,$month,$day,$year));
+               }
+               if ($helpmsg !== '')
+               {
+                       $options .= " onFocus=\"self.status='".addslashes($helpmsg)."'; return true;\"" .
+                               " onBlur=\"self.status=''; return true;\"";
+               }
+               return
+               '<input type="text" id="'.$name.'" name="'.$name.'" size="12" value="'.$date.'"'.$options.'/>
+               <script type="text/javascript">
+               document.writeln(\'<img id="'.$name.'-trigger" src="'.$GLOBALS['phpgw']->common->find_image('phpgwapi','cal').'" title="'.lang('Select date').'" style="cursor:pointer; cursor:hand;"/>\');
+               Calendar.setup(
+                       {
+                               inputField  : "'.$name.'",
+                               button      : "'.$name.'-trigger",
+                               '.$setup.'
+                       }
+               );
+               </script>
+               ';
+       }
+
+       /*!
+       @function input2date
+       @syntax input2date( $datestr,$raw='raw',$day='day',$month='month',$year='year' )
+       @author ralfbecker
+       @abstract converts the date-string back to an array with year, month, day and a timestamp
+       @param $datestr content of the inputfield generated by jscalendar::input()
+       @param $raw key of the timestamp-field in the returned array or False of no timestamp
+       @param $day,$month,$year keys for the array, eg. to set mday instead of day
+       */
+       function input2date($datestr,$raw='raw',$day='day',$month='month',$year='year')
+       {
+               if ($datestr === '')
+               {
+                       return False;
+               }
+               $fields = split('[./-]',$datestr);
+               foreach(split('[./-]',$this->dateformat) as $n => $field)
+               {
+                       $date[$field] = intval($fields[$n]);
+                       if($field == 'M')
+                       {
+                               for($i=1; $i <=12; $i++)
+                               {
+                                       if(date('M',mktime(0,0,0,$i,1,2000)) == $fields[$n])
+                                       {
+                                               $date['m'] = $i;
+                                       }
+                               }
+                       }
+               }
+               $ret = array(
+                       $year  => $date['Y'],
+                       $month => $date['m'],
+                       $day   => $date['d']
+               );
+               if ($raw)
+               {
+                       $ret[$raw] = mktime(12,0,0,$date['m'],$date['d'],$date['Y']);
+               }
+               //echo "<p>jscalendar::input2date('$datestr','$raw',$day','$month','$year') = "; print_r($ret); echo "</p>\n";
+
+               return $ret;
+       }
+}
diff --git a/setup/db_config b/setup/db_config
new file mode 100644 (file)
index 0000000..b6d6cb3
--- /dev/null
@@ -0,0 +1,13 @@
+################################################################################
+# This is a perl module included by the perl scripts for this EQ application.
+# You must modify these values to match your system configuration.
+# Save the resulting file as "db_config.local" in this setup dir.
+# This will prevent your settings from being overwritten by future code updates.
+################################################################################
+
+$dbname = "phpgroupware";
+$dbhost = "192.168.0.2"; # This can be an IP address or name
+$dbport = 3306;
+$dbuser = "phpgroupware"; # This may require an additional '\@localhost'
+$dbpass = "phpgroupware";
+
diff --git a/setup/eq_config b/setup/eq_config
new file mode 100644 (file)
index 0000000..eadd5b4
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+
+///////////////////////////////////////////////////////////////////////////////////
+// This is a configuration/preferences file for your EQ application.
+// You must modify these values to match your system configuration.
+// Save the resulting file as "db_config.local" in this setup dir.
+// This will prevent your settings from being overwritten by future code updates.
+///////////////////////////////////////////////////////////////////////////////////
+
+// The full path to a directory readable and writable by your webserver user
+// that will be used to dump the MLS data uploaded via the web interface to.
+$this->upload_target_path = "/home/users/eqpres/eq_data";
+
+// The full path to the installation location of this module
+$this->application_path = "/usr/local/www/data-dist/phpgroupware/eq";
+
+// The full path to the unzip application
+$this->unzip_path = "/usr/local/bin/unzip";
+
+// Use drop down lists when specifying times in the scheduling tools.
+// If set to 0, free form text fields for the hour and minutes will be used instead.
+// If set to 1, drop down lists will be used for the hour and minute fields
+$this->time_drop_down_lists = 1;
+
+// Compute hometeaching interview stats per month or per quarter
+// If set to 0, stats will be computed per quarter.
+// If set to 1, stats will be computed per month.
+$this->monthly_hometeaching_interview_stats = 0;
+
+// Specify the minute interval increment to use in the time drop down lists
+$this->time_drop_down_list_inc = 15;
+
+// The default visit appointment duration in minutes
+$this->default_visit_appt_duration = 45;
+
+// The default ppi appointment duration in minutes
+$this->default_ppi_appt_duration = 30;
+
+// The default number of months of hometeaching history to show
+$this->default_ht_num_months = 3;
+
+// The default number of months of ppi history to show
+$this->default_ppi_num_months = 3;
+
+// The default number of years of ppi history to show
+$this->default_ppi_num_years = 0;
+
+// The default number of quarters of hometeaching interviews to show
+$this->default_int_num_quarters = 1;
+
+// The default number of years of hometeaching interviews to show
+$this->default_int_num_years = 0;
+
+// The default number of quarters of attendance to show
+$this->default_att_num_quarters = 1;
+
+// The default nubmer of years of visits to show
+$this->default_vis_num_years = 1;
+
+// The maximum number of districts you will ever need to create
+$this->max_num_districts = 4;
+
+?>
index 6e753040e1387b3c024fb66dec0321ebfdaa34e6..9c64406ac441e5085f91376e46fe90973ea54167 100644 (file)
@@ -14,7 +14,7 @@
        /* Basic information about this app */
        $setup_info['eq']['name']      = 'eq';
        $setup_info['eq']['title']     = 'Elders Quorum Tools';
-       $setup_info['eq']['version']   = '0.0.1.001';
+       $setup_info['eq']['version']   = '0.2.0';
        $setup_info['eq']['app_order'] = 8;
        $setup_info['eq']['enable']    = 1;
        
index 664cdb809c168414164ec7ce44398bb83c2b764a..7d0add889529ac0c16c668e73d87136a7152a3d1 100644 (file)
@@ -159,19 +159,6 @@ CREATE TABLE `eq_family` (
   PRIMARY KEY  (`family`)
 ) ENGINE=MyISAM AUTO_INCREMENT=277 DEFAULT CHARSET=latin1;
 
---
--- Table structure for table `eq_interview`
---
-CREATE TABLE `eq_interview` (
-  `interview` int(16) unsigned NOT NULL auto_increment,
-  `interviewer` int(16) unsigned default NULL,
-  `elder` int(16) unsigned default NULL,
-  `aaronic` int(16) unsigned NOT NULL default '0',
-  `date` date default NULL,
-  `notes` text,
-  PRIMARY KEY  (`interview`)
-) ENGINE=MyISAM AUTO_INCREMENT=65 DEFAULT CHARSET=latin1;
-
 --
 -- Table structure for table `eq_parent`
 --
@@ -203,6 +190,7 @@ CREATE TABLE `eq_ppi` (
   `ppi` int(16) unsigned NOT NULL auto_increment,
   `interviewer` int(16) unsigned default NULL,
   `elder` int(16) unsigned default NULL,
+  `aaronic` int(16) unsigned NOT NULL default '0',
   `date` date default NULL,
   `notes` text,
   `eqpresppi` tinyint(1) default '0',
@@ -222,6 +210,7 @@ CREATE TABLE `eq_presidency` (
   `president` tinyint(1) default '0',
   `counselor` tinyint(1) default '0',
   `secretary` tinyint(1) default '0',
+  `eqpres` tinyint(1) default '0',
   `valid` tinyint(1) default '1',
   KEY `presidency` (`presidency`),
   KEY `elder` (`elder`)
index 560dadf06cb226e976ee2ec512b15aa22435af97..a8a3cdf23de9aaf1a2f9d3064a06090b4493547c 100644 (file)
             {table_data}
             </table>
             <b>Notes:</b>
+            <br>- The District is a drop-down list. Please assign a unique district number per district supervisor.
            <br>- The President, Counselor, Secretary, and EQ Presidency fields are boolean value (true|false) flags.
             <br>- If a member of the presidency is not a District Leader, make sure to set their "District=0".
             <br>- If a district leader is not a member of the presidency, add them without setting any other flags except the district.
             <br>- You can only add 1 new presidency member at a time (1 per each update request to the table).
-           <br>- Make sure you have at least 1 EQ Presidency member that is marked as EQ Presidency=1 with no Elder selected.
+           <br>- Make sure you have 1 EQ Presidency member that is marked as EQ Presidency=1 with no Elder selected.
             <br>This entry is used to email the entire presidency, and its email address should cause that to happen.
            <br><br>
            <input type="submit" value="Update EQ Presidency Table">
index a18055fff5fcd031c70b08ef5b1b8d55f622a1e8..b8b3ded067dd8b6cde2f2c402f8c88bcf803827c 100644 (file)
@@ -47,6 +47,7 @@
                <tr bgcolor="#c9c9c9"><font face="{font}">{header_row}</tr>
                {table_data}
                <tr>
+               <tr><td colspan=5 align=center><i>Note: The highest priority is 1, the lowest priority is 30</i></td></tr>
                <td></td><td></td><td></td><td></td>
                <td height="50" align="right">
                        <font face="{font}"><input type="submit" name="save" value="{lang_save}"></font>
index 5d2214786a26f488789bef373f3134c2fd517e93..74ee4694570b4452909e6e1bbcc423615acd8ef1 100644 (file)
@@ -6,7 +6,6 @@
        <input type=hidden name=elder value={elder}>
        <input type=hidden name=aaronic value={aaronic}>
        <input type=hidden name=companionship value={companionship}>
-       <input type=hidden name=eqpresppi value={eqpresppi}>
        <table border="0" width="60%" cellspacing="2" cellpadding="2">
                <tr>
                        <td align="center" bgcolor="#c9c9c9"><font face="{font}"><b>{lang_action}:&nbsp;{name}</b></font></td>
                </tr>
                <tr>
                        <td align="left"><font face="{font}"><b>Interviewer:</b>&nbsp;
-                       <select name="interviewer" disabled>
+                       <select name="interviewer" {disabled}>
 <!-- BEGIN interviewer_list -->
                        <option value={interviewer}>{interviewer_name}</option>
 <!-- END interviewer_list -->
                        </select>
+                       &nbsp; <input type="checkbox" name="eqpresppi" value="1" {eqpresppi_checked} {disabled}>
+                       Yearly PPI
                </tr>
                <tr>
                        <td align="left"><font face="{font}"><b>Date:</b>&nbsp;
index 6fb025ac7a3dbd82b92ada99def756f25ad6e9bb..a130178eee5d13a05c75bd3797b5f05b286d324f 100644 (file)
@@ -47,6 +47,7 @@
                <tr bgcolor="#c9c9c9"><font face="{font}">{header_row}</tr>
                {table_data}
                <tr>
+               <tr><td colspan=5 align=center><i>Note: The highest priority is 1, the lowest priority is 30</i></td></tr>
                <td></td><td></td><td></td><td></td>
                <td height="50" align="right">
                        <font face="{font}"><input type="submit" name="save" value="{lang_save}"></font>
index 5d2214786a26f488789bef373f3134c2fd517e93..f6b6817c5c943cdc58ec5847556273c062efb6a8 100644 (file)
@@ -6,7 +6,6 @@
        <input type=hidden name=elder value={elder}>
        <input type=hidden name=aaronic value={aaronic}>
        <input type=hidden name=companionship value={companionship}>
-       <input type=hidden name=eqpresppi value={eqpresppi}>
        <table border="0" width="60%" cellspacing="2" cellpadding="2">
                <tr>
                        <td align="center" bgcolor="#c9c9c9"><font face="{font}"><b>{lang_action}:&nbsp;{name}</b></font></td>
                </tr>
                <tr>
                        <td align="left"><font face="{font}"><b>Interviewer:</b>&nbsp;
-                       <select name="interviewer" disabled>
+                       <select name="interviewer">
 <!-- BEGIN interviewer_list -->
                        <option value={interviewer}>{interviewer_name}</option>
 <!-- END interviewer_list -->
                        </select>
+                       &nbsp; <input type="checkbox" name="eqpresppi" value="1" {eqpresppi_checked} {disabled}>
+                       Yearly PPI
                </tr>
                <tr>
                        <td align="left"><font face="{font}"><b>Date:</b>&nbsp;
index 51ccf37bbbe5e68eeb55edfb23ad2395ae004969..7b6431f4c1e5407e338983cac92cb24cd15437b2 100644 (file)
@@ -38,7 +38,6 @@
        </table>
 <!-- END appt_list -->
 
-
 <!-- BEGIN family_list -->
        <table border="0" width="{table_width}" cellspacing="2" cellpadding="2">
                <tr>
@@ -49,6 +48,7 @@
                <tr bgcolor="#c9c9c9"><font face="{font}">{header_row}</tr>
                {table_data}
                <tr>
+               <tr><td colspan=5 align=center><i>Note: The highest priority is 1, the lowest priority is 30</i></td></tr>
                <td></td><td></td><td></td><td></td>
                <td height="50" align="right">
                        <font face="{font}"><input type="submit" name="save" value="{lang_save}"></font>
@@ -60,6 +60,7 @@
        </table>
 <!-- END family_list -->
 
+
        <table border="0" width="{completed_table_width}" cellspacing="2" cellpadding="2">
                <tr>
                        <td align="center" bgcolor="#c9c9c9" colspan=20>