[LON-CAPA-cvs] cvs: loncom /enrollment Enrollment.pm /html/adm/help/tex Course_Automated_Enrollment.tex Domain_Configuration_Auto_Enrollment.tex /interface domainprefs.pm loncoursedata.pm lonmodifycourse.pm lonpopulate.pm lonuserutils.pm selfenroll.pm /lonnet/perl lonnet.pm

raeburn raeburn at source.lon-capa.org
Sun Jul 24 10:35:45 EDT 2016


raeburn		Sun Jul 24 14:35:45 2016 EDT

  Modified files:              
    /loncom/interface	domainprefs.pm loncoursedata.pm 
                     	lonmodifycourse.pm lonpopulate.pm lonuserutils.pm 
                     	selfenroll.pm 
    /loncom/enrollment	Enrollment.pm 
    /loncom/lonnet/perl	lonnet.pm 
    /loncom/html/adm/help/tex	Domain_Configuration_Auto_Enrollment.tex 
                             	Course_Automated_Enrollment.tex 
  Log:
  - Bug 5464
    Can set failsafe value in domain (or override in Auto-enollment course
    configuration to avoid unwanted dropping of students when no data are
    retrieved for a particular inststitutional section.
  
  
-------------- next part --------------
Index: loncom/interface/domainprefs.pm
diff -u loncom/interface/domainprefs.pm:1.273 loncom/interface/domainprefs.pm:1.274
--- loncom/interface/domainprefs.pm:1.273	Mon Jun  6 17:40:47 2016
+++ loncom/interface/domainprefs.pm	Sun Jul 24 14:34:59 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to set domain-wide configuration settings
 #
-# $Id: domainprefs.pm,v 1.273 2016/06/06 17:40:47 raeburn Exp $
+# $Id: domainprefs.pm,v 1.274 2016/07/24 14:34:59 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -2497,7 +2497,7 @@
 sub print_autoenroll {
     my ($dom,$settings,$rowtotal) = @_;
     my $autorun = &Apache::lonnet::auto_run(undef,$dom),
-    my ($defdom,$runon,$runoff,$coownerson,$coownersoff);
+    my ($defdom,$runon,$runoff,$coownerson,$coownersoff,$failsafe);
     if (ref($settings) eq 'HASH') {
         if (exists($settings->{'run'})) {
             if ($settings->{'run'} eq '0') {
@@ -2531,6 +2531,9 @@
         if (exists($settings->{'sender_domain'})) {
             $defdom = $settings->{'sender_domain'};
         }
+        if (exists($settings->{'autofailsafe'})) {
+            $failsafe = $settings->{'autofailsafe'};
+        }
     } else {
         if ($autorun) {
             $runon = ' checked="checked" ';
@@ -2566,8 +2569,12 @@
                   $coownerson.' value="1" />'.&mt('Yes').'</label> '.
                   '<label><input type="radio" name="autoassign_coowners"'.
                   $coownersoff.' value="0" />'.&mt('No').'</label></span></td>'.
-                  '</tr>';
-    $$rowtotal += 3;
+                  '</tr><tr>'.
+                  '<td>'.&mt('Failsafe for no drops when institutional data missing').'</td>'.
+                  '<td class="LC_right_item"><span class="LC_nobreak">'.
+                  '<input type="text" name="autoenroll_failsafe"'.
+                  ' value="'.$failsafe.'" size="4" /></td></tr>';
+    $$rowtotal += 4;
     return $datatable;
 }
 
@@ -8911,7 +8918,8 @@
     my $autorun = &Apache::lonnet::auto_run(undef,$dom),
     my %title = ( run => 'Auto-enrollment active',
                   sender => 'Sender for notification messages',
-                  coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)');
+                  coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)',
+                  failsafe => 'Failsafe for no drops if institutional data missing for a section');
     my @offon = ('off','on');
     my $sender_uname = $env{'form.sender_uname'};
     my $sender_domain = $env{'form.sender_domain'};
@@ -8921,11 +8929,17 @@
         $sender_domain = '';
     }
     my $coowners = $env{'form.autoassign_coowners'};
+    my $failsafe = $env{'form.autoenroll_failsafe'};
+    $failsafe =~ s{^\s+|\s+$}{}g;
+    if ($failsafe =~ /\D/) {
+        undef($failsafe);
+    }
     my %autoenrollhash =  (
                        autoenroll => { 'run' => $env{'form.autoenroll_run'},
                                        'sender_uname' => $sender_uname,
                                        'sender_domain' => $sender_domain,
                                        'co-owners' => $coowners,
+                                       'autofailsafe' => $failsafe,
                                 }
                      );
     my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash,
@@ -8952,7 +8966,10 @@
             }
         } elsif ($coowners) {
             $changes{'coowners'} = 1;
-        }      
+        }
+        if ($currautoenroll{'autofailsafe'} ne $failsafe) {
+            $changes{'autofailsafe'} = 1;
+        }
         if (keys(%changes) > 0) {
             $resulttext = &mt('Changes made:').'<ul>';
             if ($changes{'run'}) {
@@ -8972,6 +8989,17 @@
                     $lastactref->{'domainconfig'} = 1;
                 }
             }
+            if ($changes{'autofailsafe'}) {
+                if ($failsafe ne '') {
+                    $resulttext .= '<li>'.&mt("$title{'failsafe'} set to [_1]",$failsafe).'</li>';
+                } else {
+                    $resulttext .= '<li>'.&mt("$title{'failsafe'} deleted");
+                }
+                &Apache::lonnet::get_domain_defaults($dom,1);
+                if (ref($lastactref) eq 'HASH') {
+                    $lastactref->{'domdefaults'} = 1;
+                }
+            }
             $resulttext .= '</ul>';
         } else {
             $resulttext = &mt('No changes made to auto-enrollment settings');
Index: loncom/interface/loncoursedata.pm
diff -u loncom/interface/loncoursedata.pm:1.198 loncom/interface/loncoursedata.pm:1.199
--- loncom/interface/loncoursedata.pm:1.198	Tue Apr 26 13:51:38 2016
+++ loncom/interface/loncoursedata.pm	Sun Jul 24 14:34:59 2016
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: loncoursedata.pm,v 1.198 2016/04/26 13:51:38 raeburn Exp $
+# $Id: loncoursedata.pm,v 1.199 2016/07/24 14:34:59 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -2398,14 +2398,15 @@
 sub CL_TYPE     { return 8; }
 sub CL_LOCKEDTYPE   { return 9; }
 sub CL_CREDITS  { return 10; }
-sub CL_GROUP    { return 11; }
-sub CL_PERMANENTEMAIL { return 12; }
-sub CL_ROLE     { return 13; }
-sub CL_EXTENT   { return 14; }
-sub CL_PHOTO   { return 15; }
-sub CL_THUMBNAIL { return 16; }
-sub CL_AUTHORQUOTA { return 17; }
-sub CL_AUTHORUSAGE { return 18; }
+sub CL_INSTSEC { return 11; }
+sub CL_GROUP    { return 12; }
+sub CL_PERMANENTEMAIL { return 13; }
+sub CL_ROLE     { return 14; }
+sub CL_EXTENT   { return 15; }
+sub CL_PHOTO   { return 16; }
+sub CL_THUMBNAIL { return 17; }
+sub CL_AUTHORQUOTA { return 18; }
+sub CL_AUTHORUSAGE { return 19; }
 
 sub get_classlist {
     my ($cdom,$cnum) = @_;
@@ -2425,9 +2426,9 @@
         }
         my ($sname,$sdom) = split(/:/,$student);
         my @Values = split(/:/,$info);
-        my ($end,$start,$id,$section,$fullname,$type,$lockedtype,$credits);
+        my ($end,$start,$id,$section,$fullname,$type,$lockedtype,$credits,$instsec);
         if (@Values > 2) {
-            ($end,$start,$id,$section,$fullname,$type,$lockedtype,$credits) = @Values;
+            ($end,$start,$id,$section,$fullname,$type,$lockedtype,$credits,$instsec) = @Values;
         } else { # We have to get the data ourselves
             ($end,$start) = @Values;
             $section = &Apache::lonnet::getsection($sdom,$sname,$cid);
@@ -2467,12 +2468,12 @@
         }
         $classlist{$student} = 
             [$sdom,$sname,$end,$start,$id,$section,$fullname,$status,$type,
-             $lockedtype,$credits];
+             $lockedtype,$credits,$instsec];
     }
     if (wantarray()) {
         return (\%classlist,['domain','username','end','start','id',
                              'section','fullname','status','type',
-                             'lockedtype','credits']);
+                             'lockedtype','credits','instsec']);
     } else {
         return \%classlist;
     }
@@ -3203,7 +3204,7 @@
 Returns a reference to a hash which contains:
  keys    '$sname:$sdom'
  values  [$sdom,$sname,$end,$start,$id,$section,$fullname,$status,$type,
-          $lockedtype,$credits]
+          $lockedtype,$credits,$instsec]
 
 The constant values CL_SDOM, CL_SNAME, CL_END, etc. can be used
 as indices into the returned list to future-proof clients against
Index: loncom/interface/lonmodifycourse.pm
diff -u loncom/interface/lonmodifycourse.pm:1.83 loncom/interface/lonmodifycourse.pm:1.84
--- loncom/interface/lonmodifycourse.pm:1.83	Wed Apr  6 17:41:52 2016
+++ loncom/interface/lonmodifycourse.pm	Sun Jul 24 14:34:59 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # handler for DC-only modifiable course settings
 #
-# $Id: lonmodifycourse.pm,v 1.83 2016/04/06 17:41:52 raeburn Exp $
+# $Id: lonmodifycourse.pm,v 1.84 2016/07/24 14:34:59 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -55,7 +55,7 @@
 sub autoenroll_keys {
     my $internals = ['coursecode','courseowner','authtype','autharg','defaultcredits',
                      'autoadds','autodrops','autostart','autoend','sectionnums',
-                     'crosslistings','co-owners'];
+                     'crosslistings','co-owners','autodropfailsafe'];
     my $accessdates = ['default_enrollment_start_date','default_enrollment_end_date'];
     return ($internals,$accessdates);
 }
@@ -124,14 +124,13 @@
                 $enrollvar{$type} =~ s/,/, /g;
             } elsif ($type eq "authtype"
                      || $type eq "autharg"    || $type eq "coursecode"
-                     || $type eq "crosslistings") {
+                     || $type eq "crosslistings" || $type eq "selfenrollmgr"
+                     || $type eq "autodropfailsafe") {
                 $enrollvar{$type} = $settings{$item};
             } elsif ($type eq 'defaultcredits') {
                 if (&showcredits($cdom)) {
                     $enrollvar{$type} = $settings{$item};
                 }
-            } elsif ($type eq 'selfenrollmgr') {
-                $enrollvar{$type} = $settings{$item};    
             } elsif ($type eq 'courseowner') {
                 if ($settings{$item} =~ /^[^:]+:[^:]+$/) {
                     $enrollvar{$type} = $settings{$item};
@@ -2131,6 +2130,7 @@
                       'sectionnums' => 'Course section number:LON-CAPA section',
                       'crosslistings' => 'Crosslisted class:LON-CAPA section',
                       'defaultcredits' => 'Credits',
+                      'autodropfailsafe' => "Failsafe section enrollment count",
                       'selfenrollmgrdc'  => "Course-specific self-enrollment configuration by Domain Coordinator",
                       'selfenrollmgrcc'  => "Course-specific self-enrollment configuration by Course personnel",
 
Index: loncom/interface/lonpopulate.pm
diff -u loncom/interface/lonpopulate.pm:1.83 loncom/interface/lonpopulate.pm:1.84
--- loncom/interface/lonpopulate.pm:1.83	Tue Jun  9 21:22:57 2015
+++ loncom/interface/lonpopulate.pm	Sun Jul 24 14:34:59 2016
@@ -1,5 +1,5 @@
 # automated enrollment configuration handler
-# $Id: lonpopulate.pm,v 1.83 2015/06/09 21:22:57 damieng Exp $
+# $Id: lonpopulate.pm,v 1.84 2016/07/24 14:34:59 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -350,6 +350,10 @@
               <td>'.&mt('Use [_1]View students and change type[_2] to display the current course roster, and (optionally) change enrollment type for selected students from "auto" to "manual" and vice versa.','<i>"','"</i>').'</td>
             </tr>
             <tr>
+            <td> </td>
+              <td>'.&mt('Use [_1]Change zero enrollment failsafe[_2] to set number of existing enrollments in an institutional section above which no automated drops occur whenever section enrollment retrieved from institutional data is zero.','<i>"','"</i>').'</td>
+            </tr>
+            <tr>
              <td colspan="2"> </td>
             </tr>
             <tr>
@@ -423,6 +427,70 @@
             <input type="hidden" name="action" value="'.$action.'" />
             <input type="hidden" name="state" value="process" />
             </form>'."\n");
+  } elsif ($action eq 'chgfailsafe') {
+      my $autofailsafe;
+      my %domconfig =
+          &Apache::lonnet::get_dom('configuration',['autoenroll'],$dom);
+      if (ref($domconfig{'autoenroll'}) eq 'HASH') {
+          $autofailsafe = $domconfig{'autoenroll'}->{'autofailsafe'};
+          if ($autofailsafe =~ /\D/) {
+              undef($autofailsafe);
+          }
+      }
+      $r->print('
+          <form name="enter" method="post" action=""><br />
+           <table width="100%" border="0" cellpadding="2" cellspacing="2">
+            <tr>
+             <td align="left"><b>'.$$tasktitleref{$action}.'</b><br /><p>'.
+             &mt('In a course where multiple institutional sections provide enrollment, the "failsafe" value can prevent automated enrollment from expiring student roles for registered students in one section, in the case where no enrollment is returned for that particular section because of a temporary institutional data retrieval problem external to LON-CAPA.').'</p>'.
+            '<p>'.&mt('For example if this value is set to 10, and the current LON-CAPA enrollment count is 11 or more for a particular course section, no role expiration will occur if the latest retrieved enrollment count is zero for that institutional section (or cross-listing).').'</p>');
+      if ($enrollvar{'autodropfailsafe'} eq '') {
+          $r->print('<p>'.&mt('Currently no course-specific failsafe value is set.').' ');
+          if ($autofailsafe eq '') {
+              $r->print(&mt('Currently no domain default failsafe is set either.'));
+          } else {
+              $r->print(&mt('The current domain default of [_1] will apply, unless a value is set here specific to this course.',$autofailsafe));
+          }
+          $r->print('</p>');
+      } else {
+          $r->print('<p>'.&mt('Currently, the course-specific failsafe is set to [_1].',"<i>$enrollvar{'autodropfailsafe'}</i>").'</p>');
+      }
+      $r->print('
+             </td>
+            </tr>
+           </table>
+           <table width="100%" border="0" cellpadding="3" cellspacing="3">
+            <tr>
+             <td><b>
+            '.&mt('Failsafe (enter an integer)').'</b>  
+              <input type="textbox" name="autodropfailsafe" value="'.$enrollvar{'autodropfailsafe'}.'" size="4" /><br />');
+       if ($enrollvar{'autodropfailsafe'}) {
+          if ($autofailsafe) {  
+              $r->print(&mt('Leave blank to use domain default of [_1].',$autofailsafe));
+          } else {
+              $r->print(&mt('Leave blank to not use.'));
+          }
+       }
+       $r->print('
+             </td>
+            </tr>
+            <tr>
+              <td> </td>
+            </tr>
+            <tr>
+              <td>'.&mt('Push "Go" to save your changes').'
+            <tr>
+              <td> </td>
+            </tr>
+            <tr>
+             <td align="right">
+              <input type="button" name="updatefailsafe" value="'.&mt('Go').'" onclick="'."process('chgfailsafe')".'" />
+             </td>
+            </tr>
+           </table>
+           <input type="hidden" name="action" value="'.$action.'" />
+           <input type="hidden" name="state" value="process" />
+           </form>'."\n");
   } elsif ($action eq 'setdates') {
       my ($start_table,$end_table) = &date_setting_table($enrollvar{autostart},$enrollvar{autoend},$action);
       my $oldstartshow = '';
@@ -1064,7 +1132,7 @@
                     </tr>
                     <tr>
                      <td align="right">
-                      <input type="button" name="showphotos" value="Go" onclick="process('."'photos'".')" />
+                      <input type="button" name="showphotos" value="'.&mt('Go').'" onclick="process('."'photos'".')" />
                      </td>
                     </tr>
                    </table>
@@ -1467,28 +1535,15 @@
 ###################################################################
 sub print_chgsettings_response {
     my ($r,$realm,$dom,$crs,$action,$tasktitleref) = @_;
-    my %settings = &Apache::lonnet::get('environment',['internal.sectionnums','internal.crosslistings','internal.autostart','internal.autoend','internal.autoadds','internal.autodrops'],$dom,$crs);
-    my ($currend,$currstart,$currsecs,$currxlists,$curradds,$currdrops,
-        $autoadds,$autodrops,$response,$warning,$warn_prefix,$warn_suffix,
-        $warnfiller);
+    my %settings = &Apache::lonnet::get('environment',['internal.autoadds','internal.autodrops'],$dom,$crs);
+    my ($curradds,$currdrops,$autoadds,$autodrops,$response,$warning,
+        $warn_prefix,$warn_suffix,$warnfiller);
     if ( defined($settings{'internal.autoadds'}) ) {
 	$curradds = $settings{'internal.autoadds'};
     }
     if ( defined($settings{'internal.autodrops'}) ) {
 	$currdrops = $settings{'internal.autodrops'};
     }
-    if ( defined($settings{'internal.autostart'}) ) {
-	$currstart = $settings{'internal.autostart'};
-    }
-    if ( defined($settings{'internal.autoend'}) ) {
-	$currend = $settings{'internal.autoend'};
-    }
-    if ( defined($settings{'internal.sectionnums'}) ) {
-	$currsecs = $settings{'internal.sectionnums'};
-    }
-    if ( defined($settings{'internal.crosslistings'}) ) {
-	$currxlists = $settings{'internal.crosslistings'}
-    }
     if ( exists($env{'form.autoadds'}) ) {
 	$autoadds=$env{'form.autoadds'};
     }
@@ -1538,7 +1593,7 @@
             unless ($warning eq '') {
 	        $response .= '<br /><span class="LC_warning">'.
                              '<b>'.&mt('Warning.').'</b> ';
-                if ($autodrops && $autodrops) {
+                if ($autoadds && $autodrops) {
                     $response .= 
                         &mt('Although you indicated that nightly adds and drops should be enabled, additional action is required.');
                 } elsif ($autoadds) {
@@ -1556,6 +1611,39 @@
     return;
 }
 
+sub print_chgfailsafe_response {
+    my ($r,$realm,$dom,$crs,$action,$tasktitleref) = @_;
+    my %settings = &Apache::lonnet::get('environment',['internal.autodropfailsafe'],
+                                        $dom,$crs);
+    my ($currfailsafe,$newfailsafe,$response);
+    if ( defined($settings{'internal.autodropfailsafe'}) ) {
+        $currfailsafe = $settings{'internal.autodropfailsafe'};
+    }
+    if (exists($env{'form.autodropfailsafe'})) {
+        $env{'form.autodropfailsafe'} =~ s{^\s+|\s+$}{}g;
+        if ($env{'form.autodropfailsafe'} !~ /\D/) { 
+            $newfailsafe = $env{'form.autodropfailsafe'};
+        }
+    }
+    if ($currfailsafe ne $newfailsafe) {
+        my %cenv = ('internal.autodropfailsafe' => $newfailsafe);
+        my $reply = &Apache::lonnet::put('environment',\%cenv,$dom,$crs);
+        if ($reply ne 'ok') {
+            $response =
+                &mt('There was a problem processing your requested changes.').' '.
+                &mt('The automated enrollment settings for this course have been left unchanged.').'<br />';
+        } elsif ($newfailsafe ne '') {
+            $response = &mt('Automated drop failsafe set to [_1]',$newfailsafe);
+        } else {
+            $response = &mt('Course-specific automated drop failsafe deleted.');
+        }
+    } else {
+        $response = &mt('The new value for the automated drop failsafe was the same as the existing value, so no changes have been made.'); 
+    }
+    &print_reply($r,$response,$$tasktitleref{$action});
+    return;
+}
+
 sub print_setdates_response {
     my ($r,$realm,$dom,$crs,$action,$tasktitleref) = @_;
     my %settings = 
@@ -2728,7 +2816,7 @@
         &Apache::lonnet::get('environment',
             ['internal.coursecode','internal.sectionnums','internal.crosslistings',
              'internal.authtype','internal.autharg','internal.showphoto','internal.defaultcredits',
-             'internal.textbook'],
+             'internal.autodropfailsafe','internal.textbook'],
             $dom,$crs);
     my $coursecode = $settings{'internal.coursecode'};
     my $authtype = $settings{'internal.authtype'};
@@ -2750,6 +2838,10 @@
             }
         }
     }
+    my $failsafe = $settings{'internal.autodropfailsafe'};
+    if ($failsafe eq '') {
+        $failsafe = $domdefaults{'autofailsafe'};
+    }
     my ($startaccess,$endaccess) = &get_dates_from_form();
     if ( exists($env{'form.updateadds'}) ) {
         $updateadds = $env{'form.updateadds'};
@@ -2784,7 +2876,7 @@
                                  ": ".$outcome);
             }
 	    if ($reply{$crs} > 0) {
-		($changecount,$response) = &LONCAPA::Enrollment::update_LC($dom,$crs,$updateadds,$updatedrops,$startaccess,$endaccess,$authtype,$autharg,$showcredits,$defaultcredits,\@allcourses,\%LC_code,\$logmsg,\$newusermsg,"updatenow",\%phototypes);
+		($changecount,$response) = &LONCAPA::Enrollment::update_LC($dom,$crs,$updateadds,$updatedrops,$startaccess,$endaccess,$authtype,$autharg,$showcredits,$defaultcredits,$failsafe,\@allcourses,\%LC_code,\$logmsg,\$newusermsg,"updatenow",\%phototypes);
 	    } else {
 		$response = &mt('There was a problem retrieving institutional class list data for the course sections and crosslisted courses which contribute enrollment to this course.').' '.
                             &mt('No updates have been carried out, and the roster remains unchanged.');
@@ -3155,6 +3247,7 @@
         &Apache::lonlocal::texthash(
                information   => 'Task information',
                chgsettings   => 'Automated adds/drops',
+               chgfailsafe   => 'Change zero enrollment failsafe',
                setdates      => 'Change enrollment dates',
                setaccess     => 'Change access dates',
                notify        => 'Notification of changes',
@@ -3171,6 +3264,7 @@
     my %tasktitle = 
         &Apache::lonlocal::texthash(
                chgsettings  => 'Changes to nightly automated enrollments',
+               chgfailsafe  => 'Changes to failsafe protection for data retrieval problems',
                setdates     => 'Changes to first and/or last automated enrollment dates',
                setaccess    => 'Changes to default start and/or end dates for student access',
                notify       => 'Notification of enrollment changes',
@@ -3208,7 +3302,7 @@
     $r->send_http_header;
 
     my @tasks = ('information','chgsettings','setdates','setaccess','notify','crosslist',
-                 'sections','photos','updatenow','updatephotos','viewclass');
+                 'sections','photos','updatenow','updatephotos','viewclass','chgfailsafe');
  
     my ($tasklong,$tasktitle) = &get_task_text();
     my $realm;
@@ -3274,6 +3368,8 @@
         &print_main_frame($r,$realm,$dom,$crs,$tasktitle);
     } elsif ($action eq "chgsettings") {
         &print_chgsettings_response($r,$realm,$dom,$crs,$action,$tasktitle);
+    } elsif ($action eq "chgfailsafe") {
+        &print_chgfailsafe_response($r,$realm,$dom,$crs,$action,$tasktitle);
     } elsif ($action eq "setdates") {
         &print_setdates_response($r,$realm,$dom,$crs,$action,$tasktitle);
     } elsif ($action eq "setaccess") {
Index: loncom/interface/lonuserutils.pm
diff -u loncom/interface/lonuserutils.pm:1.173 loncom/interface/lonuserutils.pm:1.174
--- loncom/interface/lonuserutils.pm:1.173	Sat Apr  2 04:30:21 2016
+++ loncom/interface/lonuserutils.pm	Sun Jul 24 14:34:59 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Utility functions for managing LON-CAPA user accounts
 #
-# $Id: lonuserutils.pm,v 1.173 2016/04/02 04:30:21 raeburn Exp $
+# $Id: lonuserutils.pm,v 1.174 2016/07/24 14:34:59 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -36,6 +36,7 @@
 use Apache::lonhtmlcommon;
 use Apache::lonlocal;
 use Apache::longroup;
+use HTML::Entities;
 use LONCAPA qw(:DEFAULT :match);
 
 ###############################################################
@@ -2413,6 +2414,7 @@
     $index->{'photo'} = &Apache::loncoursedata::CL_PHOTO();
     $index->{'thumbnail'} = &Apache::loncoursedata::CL_THUMBNAIL();
     $index->{'credits'} = &Apache::loncoursedata::CL_CREDITS();
+    $index->{'instsec'} = &Apache::loncoursedata::CL_INSTSEC();
     $index->{'authorquota'} = &Apache::loncoursedata::CL_AUTHORQUOTA();
     $index->{'authorusage'} = &Apache::loncoursedata::CL_AUTHORUSAGE();
     foreach my $key (keys(%{$index})) {
@@ -3056,13 +3058,14 @@
                                 if ($role eq 'st') {
                                     $checkval .= ':'.$in{'type'}.':'.
                                                  $in{'lockedtype'}.':'.
-                                                 $in{'credits'};
+                                                 $in{'credits'}.':'.
+                                                 &escape($in{'instsec'});
                                 }
                              }
                         }
                         if ($showcheckbox) {
                             $r->print('<td><input type="checkbox" name="'.
-                                      'actionlist" value="'.$checkval.'" /></td>');
+                                      'actionlist" value="'.&HTML::Entities::encode($checkval,'&<>"').'" /></td>');
                         } else {
                             $r->print('<td> </td>');
                         }
@@ -3077,7 +3080,7 @@
                 if ($item eq 'username') {
                     $r->print('<td>'.&print_username_link($mode,\%in).'</td>');
                 } elsif (($item eq 'start' || $item eq 'end') && ($actionselect)) {
-                    $r->print('<td>'.$in{$item}.'<input type="hidden" name="'.$checkval.'_'.$item.'" value="'.$sdata->[$index{$item}].'" /></td>'."\n");
+                    $r->print('<td>'.$in{$item}.'<input type="hidden" name="'.&HTML::Entities::encode($checkval.'_'.$item.'" value="'.$sdata->[$index{$item}],'&<>"').'" /></td>'."\n");
                 } elsif ($item eq 'status') {
                     my $showitem = $in{$item};
                     if (defined($ltstatus{$in{$item}})) {
@@ -4980,7 +4983,7 @@
     foreach my $item (@changelist) {
         my ($role,$uname,$udom,$cid,$sec,$scope,$result,$type,$locktype,
             @sections,$scopestem,$singlesec,$showsecs,$warn_singlesec,
-            $nothingtodo,$keepnosection,$credits);
+            $nothingtodo,$keepnosection,$credits,$instsec);
         if ($choice eq 'drop') {
             ($uname,$udom,$sec) = split(/:/,$item,-1);
             $role = 'st';
@@ -4993,8 +4996,9 @@
                 $scope = $scopestem.'/'.$sec;
             }
         } elsif ($context eq 'course') {
-            ($uname,$udom,$role,$sec,$type,$locktype,$credits) =
-                split(/\:/,$item);
+            ($uname,$udom,$role,$sec,$type,$locktype,$credits,$instsec) =
+                split(/\:/,$item,8);
+            $instsec = &unescape($instsec);
             $cid = $env{'request.course.id'};
             $scopestem = '/'.$cid;
             $scopestem =~s/\_/\//g;
@@ -5013,8 +5017,9 @@
             } elsif ($setting eq 'author') { 
                 ($uname,$udom,$role,$scope) = split(/\:/,$item);
             } elsif ($setting eq 'course') {
-                ($uname,$udom,$role,$cid,$sec,$type,$locktype,$credits) = 
-                    split(/\:/,$item);
+                ($uname,$udom,$role,$cid,$sec,$type,$locktype,$credits,$instsec) = 
+                    split(/\:/,$item,9);
+                $instsec = &unescape($instsec);
                 $scope = '/'.$cid;
                 $scope =~s/\_/\//g;
                 if ($sec ne '') {
@@ -5036,7 +5041,7 @@
             $end = $now; 
             if ($role eq 'st') {
                 $result = 
-                    &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits);
+                    &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
             } else {
                 $result = 
                     &Apache::lonnet::revokerole($udom,$uname,$scope,$role,
@@ -5044,7 +5049,7 @@
             }
         } elsif ($choice eq 'delete') {
             if ($role eq 'st') {
-                &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$now,$start,$type,$locktype,$cid,'',$context,$credits);
+                &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$now,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
             }
             $result =
                 &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$now,
@@ -5057,7 +5062,7 @@
             }
             if ($choice eq 'reenable') {
                 if ($role eq 'st') {
-                    $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits);
+                    $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
                 } else {
                     $result = 
                         &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
@@ -5065,14 +5070,14 @@
                 }
             } elsif ($choice eq 'activate') {
                 if ($role eq 'st') {
-                    $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits);
+                    $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
                 } else {
                     $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
                                             $now,'','',$context);
                 }
             } elsif ($choice eq 'chgdates') {
                 if ($role eq 'st') {
-                    $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits);
+                    $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
                 } else {
                     $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
                                                 $start,'','',$context);
@@ -5142,7 +5147,7 @@
                     } else {
                         if ($role eq 'st') {
                             $result = 
-                                &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,undef,$end,$start,$type,$locktype,$cid,'',$context,$credits);
+                                &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,undef,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
                         } else {
                             my $newscope = $scopestem;
                             $result = &Apache::lonnet::assignrole($udom,$uname,$newscope,$role,$end,$start,'','',$context);
@@ -5156,7 +5161,7 @@
                     foreach my $newsec (@newsecs) {
                         if (!grep(/^\Q$newsec\E$/, at retained)) {
                             if ($role eq 'st') {
-                                $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$newsec,$end,$start,$type,$locktype,$cid,'',$context,$credits);
+                                $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$newsec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
                                 if (@newsecs > 1) {
                                     my $showsingle; 
                                     if ($newsec eq '') {
Index: loncom/interface/selfenroll.pm
diff -u loncom/interface/selfenroll.pm:1.32 loncom/interface/selfenroll.pm:1.33
--- loncom/interface/selfenroll.pm:1.32	Tue Jun  9 21:22:57 2015
+++ loncom/interface/selfenroll.pm	Sun Jul 24 14:35:00 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Allow users to self-enroll in a course
 #
-# $Id: selfenroll.pm,v 1.32 2015/06/09 21:22:57 damieng Exp $
+# $Id: selfenroll.pm,v 1.33 2016/07/24 14:35:00 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -438,8 +438,10 @@
         if ($selfenroll_section eq 'none') {
             $usec = '';
         }
+        my $instcid;
         if ($selfenroll_registered) {
-            my ($registered,$instsec,$message) = &check_registered($cdom,$cnum);
+            my ($registered,$instsec,$message);
+            my ($registered,$instsec,$instcid,$message) = &check_registered($cdom,$cnum);
             $usec = $instsec;
             if (!$registered) {
                 $r->print('<h3>'.&mt('Self-enrollment unavailable').'</h3>'.
@@ -462,7 +464,7 @@
             my $enrollresult = 
                 &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,
                         undef,undef,$usec,$selfenroll_access_end,$selfenroll_access_start,
-                       'selfenroll',undef,$cdom.'_'.$cnum,$selfenroll);
+                       'selfenroll',undef,$cdom.'_'.$cnum,$selfenroll,'selfenroll','',$instcid);
             if ($enrollresult eq 'ok') {
                 my (%userroles,%newrole,%newgroups);
                 my $role = 'st';
@@ -785,7 +787,7 @@
 
 sub check_registered {
     my ($cdom,$cnum) = @_;
-    my ($registered,$instsec,$message);
+    my ($registered,$instsec,$instcid,$message);
     my %settings = &Apache::lonnet::get('environment',['internal.coursecode',
                                         'internal.sectionnums',
                                         'internal.crosslistings'],$cdom,$cnum);
@@ -805,6 +807,7 @@
                     if (defined($enrolled{$env{'user.name'}})) {
                         $registered = 1;
                         $instsec = $LC_code{$class};
+                        $instcid = $class;
                         last;
                     }
                 }
@@ -817,7 +820,7 @@
     } else {
         $message = &mt('As no institutional course sections are currently associated with this course, your registration status is undetermined.'); 
     }
-    return ($registered,$instsec,$message);
+    return ($registered,$instsec,$instcid,$message);
 }
 
 1;
Index: loncom/enrollment/Enrollment.pm
diff -u loncom/enrollment/Enrollment.pm:1.48 loncom/enrollment/Enrollment.pm:1.49
--- loncom/enrollment/Enrollment.pm:1.48	Fri Jun  3 01:22:36 2016
+++ loncom/enrollment/Enrollment.pm	Sun Jul 24 14:35:15 2016
@@ -1,5 +1,5 @@
 # Automated Enrollment manager
-# $Id: Enrollment.pm,v 1.48 2016/06/03 01:22:36 raeburn Exp $
+# $Id: Enrollment.pm,v 1.49 2016/07/24 14:35:15 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -39,8 +39,8 @@
 
 sub update_LC {
     my ($dom,$crs,$adds,$drops,$startdate,$enddate,$authtype,$autharg,
-        $showcredits,$defaultcredits,$classesref,$groupref,$logmsg,$newusermsg,
-        $context,$phototypes) = @_;
+        $showcredits,$defaultcredits,$autofailsafe,$classesref,$groupref,
+        $logmsg,$newusermsg,$context,$phototypes) = @_;
 # Get institutional code and title of this class
     my %courseinfo = ();
     &get_courseinfo($dom,$crs,\%courseinfo);
@@ -56,6 +56,7 @@
     my $type=&Apache::loncoursedata::CL_TYPE;
     my $lockedtype=&Apache::loncoursedata::CL_LOCKEDTYPE;
     my $credidx=&Apache::loncoursedata::CL_CREDITS;
+    my $instidx = &Apache::loncoursedata::CL_INSTSEC;
     my @localstudents = ();
     my @futurestudents = ();
     my @activestudents = ();
@@ -130,9 +131,11 @@
     my %place = &place_hash(); 
     my %ucount = ();
     my %enrollinfo = ();
+    my %classcount;
     foreach my $class (@{$classesref}) {
         my %enrolled = ();
         &parse_classlist($$configvars{'lonDaemons'},$dom,$crs,$class,\%place,$$groupref{$class},\%enrolled);
+        $classcount{$class} = scalar(keys(%enrolled));
         foreach my $uname (sort keys %enrolled ) {
             if (!grep/^$uname$/, at reg_students) {
                 push @reg_students,$uname;
@@ -209,7 +212,7 @@
         unless ($uname eq '') {
             my %uidhash=&Apache::lonnet::idrget($dom,$uname);
             my @stuinfo = @{$enrollinfo{$uname}};
-            my ($access,$added,$inststatus);
+            my ($access,$added,$inststatus,$instsec);
             my $credits;
             if ($showcredits) {
                 $credits = $stuinfo[$place{'credits'}];
@@ -219,6 +222,7 @@
                 }
             }
             $inststatus = $stuinfo[$place{inststatus}];
+            $instsec = $stuinfo[$place{instsec}];
             if (grep/^$uname$/, at localstudents) {
 # Check for studentID changes
                 if ( ($uidhash{$uname}) && ($uidhash{$uname} !~ /error\:/) )  {
@@ -255,7 +259,7 @@
                         &execute_add($context,'switchtype',$uname,$dom,$auth,
                                      $authparam,$first,$middle,$last,$gene,
                                      $pid,$usec,$end,$start,$emailenc,
-                                     $credits,$cid,\$addresult,\$enrollcount,
+                                     $credits,$instsec,$cid,\$addresult,\$enrollcount,
                                      $linefeed,$logmsg);
                         $added = 1;
                     }
@@ -266,7 +270,7 @@
                     if ( (grep/^$uname$/, at futurestudents) && ($$currlist{$uname}[$type] eq "auto") && ($adds == 1) ) {
                         my $datechange = &datechange_check($$currlist{$uname}[$cstart],$$currlist{$uname}[$cend],$startdate,$enddate);
                         if ($datechange) {
-                            my $modify_access_result = &Apache::lonnet::modify_student_enrollment($dom,$uname,undef,undef,undef,undef,undef,$stuinfo[ $place{groupID} ],$enddate,$startdate,'auto','',$cid,'',$context,$credits);
+                            my $modify_access_result = &Apache::lonnet::modify_student_enrollment($dom,$uname,undef,undef,undef,undef,undef,$stuinfo[ $place{groupID} ],$enddate,$startdate,'auto','',$cid,'',$context,$credits,$instsec);
                             $access = &showaccess($enddate,$startdate);
                             if ($modify_access_result =~ /^ok/) {
                                 $$logmsg .= &mt('Change in access dates for [_1].',$uname).$access.$linefeed;
@@ -289,9 +293,9 @@
                         if ($expire_role_result eq 'ok') {
                             my $modify_section_result;
                             if (grep/^$uname$/, at activestudents) {
-                                $modify_section_result = &Apache::lonnet::modify_student_enrollment($dom,$uname,undef,undef,undef,undef,undef,$stuinfo[ $place{groupID} ],$$currlist{$uname}[$cend],$$currlist{$uname}[$cstart],'auto','',$cid,'',$context,$credits);
+                                $modify_section_result = &Apache::lonnet::modify_student_enrollment($dom,$uname,undef,undef,undef,undef,undef,$stuinfo[ $place{groupID} ],$$currlist{$uname}[$cend],$$currlist{$uname}[$cstart],'auto','',$cid,'',$context,$credits,$instsec);
                             } else {
-                                $modify_section_result =  &Apache::lonnet::modify_student_enrollment($dom,$uname,undef,undef,undef,undef,undef,$stuinfo[ $place{groupID} ],$enddate,$startdate,'auto','',$cid,'',$context,$credits);
+                                $modify_section_result =  &Apache::lonnet::modify_student_enrollment($dom,$uname,undef,undef,undef,undef,undef,$stuinfo[ $place{groupID} ],$enddate,$startdate,'auto','',$cid,'',$context,$credits,$instsec);
                                 $access =  &showaccess($enddate,$startdate);
                             }
                             if ($modify_section_result =~ /^ok/) {
@@ -313,7 +317,7 @@
                 if (($showcredits) && 
                     ($$currlist{$uname}[$credidx] ne $credits) && (!$added)) {
                     my $modify_credits_result =
-                        &Apache::lonnet::modify_student_enrollment($dom,$uname,undef,undef,undef,undef,undef,$stuinfo[ $place{groupID} ],$enddate,$startdate,'auto','',$cid,'',$context,$credits);
+                        &Apache::lonnet::modify_student_enrollment($dom,$uname,undef,undef,undef,undef,undef,$stuinfo[ $place{groupID} ],$enddate,$startdate,'auto','',$cid,'',$context,$credits,$instsec);
                     if ($modify_credits_result =~ /^ok/) {
                         if ($credits ne '') {
                             $$logmsg .= &mt('Credits change for [_1] from [_2] to [_3].',$uname,$$currlist{$uname}[$credidx],$credits).$linefeed;
@@ -324,6 +328,16 @@
                         $$logmsg .= &mt('Error when attempting to change credits for [_1] in section: [_2] -error [_3].',$uname,$stuinfo[$place{groupID}],$modify_credits_result).$linefeed;
                     }
                 }
+# Check for institutional section change
+                if ($$currlist{$uname}[$instidx] ne $instsec) {
+                    my $modify_instsec_result =
+                        &Apache::lonnet::modify_student_enrollment($dom,$uname,undef,undef,undef,undef,undef,$stuinfo[ $place{groupID} ],$enddate,$startdate,'auto','',$cid,'',$context,$credits,$instsec);
+                    if ($modify_instsec_result =~ /^ok/) {
+                        $$logmsg .= &mt('Institutional section change for [_1] from [_2] to [_3].',$uname,$$currlist{$uname}[$instidx],$instsec).$linefeed;
+                    } else {
+                        $$logmsg .= &mt('Error when attempting to change institutional section for [_1] in section: [_2] -error [_3].',$uname,$stuinfo[$place{groupID}],$modify_instsec_result).$linefeed;
+                    }
+                }
             } else {
 # Check for changed usernames by checking studentIDs
                 if ( ($stuinfo[ $place{studentID} ] ne '') && (grep/^$stuinfo[ $place{studentID} ]$/, at LCids) ) {
@@ -365,6 +379,7 @@
                                     'context' => $context,
                                     'linefeed' => $linefeed,
                                     'inststatus' => $inststatus,
+                                    'instsec'  => $instsec,
                                     'role' => 'st',
                                    };
                         if ($credits) {
@@ -374,7 +389,7 @@
                     } else {
                         &execute_add($context,'newstudent',$uname,$dom,$auth,
                                      $authparam,$first,$middle,$last,$gene,$pid,
-                                     $usec,$end,$start,$emailenc,$credits,
+                                     $usec,$end,$start,$emailenc,$credits,$instsec,
                                      $cid,\$addresult,\$enrollcount,$linefeed,
                                      $logmsg);
                     }
@@ -420,6 +435,7 @@
 
 # Do drops
     if ( ($drops == 1) && (@reg_students > 0) ) {
+        my %delaydrops;
         foreach my $uname (@localstudents) {
             if ($$currlist{$uname}[$type] eq "auto") {
                 my @saved = ();
@@ -431,6 +447,17 @@
                             push @saved,$uname;
                         }
                     } elsif (@saved == 0) {
+# Check enrollment count for institutional section of student to be dropped 
+                        if ($$currlist{$uname}[$instidx]) {
+                            if (exists($classcount{$$currlist{$uname}[$instidx]})) {
+                                if ($classcount{$$currlist{$uname}[$instidx]} == 0) {
+                                    if ($autofailsafe) {
+                                        push(@{$delaydrops{$$currlist{$uname}[$instidx]}},$uname);    
+                                        next;
+                                    }
+                                }
+                            }
+                        }
                         my $drop_reply = &Apache::lonnet::modifystudent($dom,$uname,'','','',undef,undef,undef,undef,$$currlist{$uname}[$sec],time,undef,undef,undef,undef,'auto','',$cid,'',$context);
                         if ($drop_reply !~ /^ok/) {
                             $$logmsg .= &mt('An error occurred during the attempt to expire the [_1] from the old section [_2] - [_3].',$uname,$$currlist{$uname}[$sec],$drop_reply).$linefeed;
@@ -446,6 +473,34 @@
                 }
             }
         }
+        if (scalar(keys(%delaydrops)) > 0) {
+            foreach my $class (keys(%delaydrops)) {
+                if (ref($delaydrops{$class}) eq 'ARRAY') {
+                    if ($autofailsafe < scalar(@{$delaydrops{$class}})) {
+                        $$logmsg .= &mt('The following students were not expired from the old section [_1] because the enrollment count retrieved for that institutional section was zero, and the number of students with roles to expire exceeded the failsafe threshold of [_2]:',$class,$autofailsafe);
+                        if ($context eq "updatenow") {
+                            $$logmsg .= join('<br />',@{$delaydrops{$class}}).$linefeed; 
+                        } elsif ($context eq "automated") {
+                            $$logmsg .= join($linefeed,@{$delaydrops{$class}}).$linefeed;
+                        }
+                    } else {
+                        foreach my $uname (@{$delaydrops{$class}}) {
+                            my $drop_reply = &Apache::lonnet::modifystudent($dom,$uname,'','','',undef,undef,undef,undef,$$currlist{$uname}[$sec],time,undef,undef,undef,undef,'auto','',$cid,'',$context);
+                            if ($drop_reply !~ /^ok/) {
+                                $$logmsg .= &mt('An error occurred during the attempt to expire the [_1] from the old section [_2] - [_3].',$uname,$$currlist{$uname}[$sec],$drop_reply).$linefeed;
+                            } else {
+                                $dropcount ++;
+                                my %userenv = &Apache::lonnet::get('environment',['firstname','lastname','id'],$dom,$uname);
+                                $dropresult .= $userenv{'firstname'}." ".$userenv{'lastname'}." (".$userenv{'id'}.") - ".$uname.' '.&mt("dropped from section: '[_1]'.",$$currlist{$uname}[$sec]).$linefeed;
+                                if ($context eq 'automated') {
+                                   $$logmsg .= &mt('User [_1] student role expired from course.',$uname).$linefeed;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
     }
 
 # Terminated explictly allowed access to student creation/modification 
@@ -523,6 +578,7 @@
     my $role = $args->{'role'};
     my $inststatus = $args->{'inststatus'};
     my $credits = $args->{'credits'};
+    my $instsec = $args->{'instsec'};
     my $create_passwd = 0;
     my $authchk = '';
     my $outcome;
@@ -567,7 +623,7 @@
                 $outcome = $result;
             }
         } else {
-            $outcome=&Apache::lonnet::modifystudent($udom,$uname,$pid,$auth,$authparam,$first,$middle,$last,$gene,$usec,$end,$start,'',undef,$emailaddr,'auto','',$cid,'',$called_context,$inststatus,$credits);
+            $outcome=&Apache::lonnet::modifystudent($udom,$uname,$pid,$auth,$authparam,$first,$middle,$last,$gene,$usec,$end,$start,'',undef,$emailaddr,'auto','',$cid,'',$called_context,$inststatus,$credits,$instsec);
         }
         if ($outcome eq 'ok') {
             my $access = &showaccess($end,$start);
@@ -686,7 +742,7 @@
 
 sub execute_add {
     my ($context,$caller,$uname,$dom,$auth,$authparam,$first,$middle,$last,
-        $gene,$pid,$usec,$end,$start,$emailenc,$credits,$cid,$addresult,
+        $gene,$pid,$usec,$end,$start,$emailenc,$credits,$instsec,$cid,$addresult,
         $enrollcount,$linefeed,$logmsg) = @_;
 # Get the user's information and authentication
     my %userenv = &Apache::lonnet::get('environment',['firstname','middlename','lastname','generation','id','critnotification','notification','permanentemail','inststatus'],$dom,$uname);
@@ -762,7 +818,7 @@
         &Apache::lonnet::modify_student_enrollment($dom,$uname,$pid,$first,$middle,
                                                    $last,$gene,$usec,$end,$start,
                                                    'auto','',$cid,'',$context,
-                                                   $credits);
+                                                   $credits,$instsec);
     if ($classlist_reply eq 'ok') {
         my $access = &showaccess($end,$start);
         my $showsec = $usec;
@@ -836,6 +892,7 @@
                  if ("@state" eq "students student") {
                      $uname = $attr->{username};
                      $$studentsref{$uname}[ $$placeref{'groupID'} ] = $groupID;
+                     $$studentsref{$uname}[ $$placeref{'instsec'} ] = $class;
                  }
             }, "tagname, attr"],
          text_h =>
@@ -948,6 +1005,7 @@
                   studentID  => 10,
                   credits    => 11,
                   inststatus => 12,
+                  instsec    => 13,
                 );
     return %place;
 }
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1313 loncom/lonnet/perl/lonnet.pm:1.1314
--- loncom/lonnet/perl/lonnet.pm:1.1313	Fri Jul  1 19:59:46 2016
+++ loncom/lonnet/perl/lonnet.pm	Sun Jul 24 14:35:29 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.1313 2016/07/01 19:59:46 raeburn Exp $
+# $Id: lonnet.pm,v 1.1314 2016/07/24 14:35:29 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -2202,7 +2202,7 @@
                                   'requestcourses','inststatus',
                                   'coursedefaults','usersessions',
                                   'requestauthor','selfenrollment',
-                                  'coursecategories'],$domain);
+                                  'coursecategories','autoenroll'],$domain);
     my @coursetypes = ('official','unofficial','community','textbook','placement');
     if (ref($domconfig{'defaults'}) eq 'HASH') {
         $domdefaults{'lang_def'} = $domconfig{'defaults'}{'lang_def'}; 
@@ -2328,6 +2328,9 @@
             $domdefaults{'catunauth'} = $domconfig{'coursecategories'}{'unauth'};
         }
     }
+    if (ref($domconfig{'autoenroll'}) eq 'HASH') {
+        $domdefaults{'autofailsafe'} = $domconfig{'autoenroll'}{'autofailsafe'};
+    }
     &do_cache_new('domdefaults',$domain,\%domdefaults,$cachetime);
     return %domdefaults;
 }
@@ -9088,7 +9091,7 @@
 sub modifystudent {
     my ($udom,$uname,$uid,$umode,$upass,$first,$middle,$last,$gene,$usec,
         $end,$start,$forceid,$desiredhome,$email,$type,$locktype,$cid,
-        $selfenroll,$context,$inststatus,$credits)=@_;
+        $selfenroll,$context,$inststatus,$credits,$instsec)=@_;
     if (!$cid) {
 	unless ($cid=$env{'request.course.id'}) {
 	    return 'not_in_class';
@@ -9104,13 +9107,13 @@
     $uid = undef if (!$forceid);
     $reply = &modify_student_enrollment($udom,$uname,$uid,$first,$middle,$last,
                                         $gene,$usec,$end,$start,$type,$locktype,
-                                        $cid,$selfenroll,$context,$credits);
+                                        $cid,$selfenroll,$context,$credits,$instsec);
     return $reply;
 }
 
 sub modify_student_enrollment {
     my ($udom,$uname,$uid,$first,$middle,$last,$gene,$usec,$end,$start,$type,
-        $locktype,$cid,$selfenroll,$context,$credits) = @_;
+        $locktype,$cid,$selfenroll,$context,$credits,$instsec) = @_;
     my ($cdom,$cnum,$chome);
     if (!$cid) {
 	unless ($cid=$env{'request.course.id'}) {
@@ -9157,7 +9160,7 @@
     my %old_entry = &Apache::lonnet::get('classlist',[$user],$cdom,$cnum);
     my $reply=cput('classlist',
 		   {$user => 
-			join(':',$end,$start,$uid,$usec,$fullname,$type,$locktype,$credits) },
+			join(':',$end,$start,$uid,$usec,$fullname,$type,$locktype,$credits,$instsec) },
 		   $cdom,$cnum);
     if (($reply eq 'ok') || ($reply eq 'delayed')) {
         &devalidate_getsection_cache($udom,$uname,$cid);
@@ -13863,6 +13866,8 @@
 
 =item $credits, number of credits student will earn from this class
 
+=item $instsec, institutional course section code for student
+
 =back
 
 
Index: loncom/html/adm/help/tex/Domain_Configuration_Auto_Enrollment.tex
diff -u loncom/html/adm/help/tex/Domain_Configuration_Auto_Enrollment.tex:1.6 loncom/html/adm/help/tex/Domain_Configuration_Auto_Enrollment.tex:1.7
--- loncom/html/adm/help/tex/Domain_Configuration_Auto_Enrollment.tex:1.6	Fri Jan 31 16:12:08 2014
+++ loncom/html/adm/help/tex/Domain_Configuration_Auto_Enrollment.tex	Sun Jul 24 14:35:45 2016
@@ -9,26 +9,36 @@
 in real time, or can involve retrieval from a data source which is
 only updated periodically.
 
-There are three configuration options: 
+There are four configuration options: 
 
 \begin{itemize}
-\item Set auto-enrollment as active or inactive in the domain. 
-\item Set the username:domain used in the notification messages sent when
-changes in enrollment occur as a result of auto-enrollment updates.
+\item \textbf{Set auto-enrollment as active or inactive in the domain} 
+\item \textbf{Set the username:domain used in the notification messages sent when
+changes in enrollment occur as a result of auto-enrollment updates.}
 By setting these to a specific user (you might create one for this
 purpose), you can view all auto-enrollment change messages for the
 entire domain by viewing the contents of the sent messages folder for that user.
-\item Automatically assign co-ownership
+\item \textbf{Automatically assign co-ownership.}
 If this is set to yes, then whenever a Course Coordinator role is assigned 
 in a course with an institutional code, a check is made to see if the user 
 to whom the role is being assigned is officially listed as instructional
 personnel. If so, and the user is not the course owner, then the user will
 be identified as a co-owner. Co-owners are listed in the course/community catalog, and
-also in the pop-up window displayed when picking a course (e.g., for cloning,
-).  For the validation to work the validate\_instcode() routine in localenroll.pm
+also in the pop-up window displayed when picking a course (e.g., for cloning).  
+For the validation to work the validate\_instcode() routine in localenroll.pm
 must have been customized to include the username supplied as the third argument
 in the query made to the institutional data source which ties instructors to
 institutional codes.
+\item \textbf{Failsafe for no drops when institutional data missing.}
+In a course for which enrollment comes from more than one institutional
+course section (including cross-listing), there is a possibility that 
+institutional data retrieval might succeed for some, but not all sections.
+In order to avoid expiring student roles in sections for which institutional
+enrollment data could not be retrieved, a failsafe value can be set.  When the
+existing enrollment in a LON-CAPA course section exceeds that failsafe value (an integer),
+dropping of existing students (identified as belonging to the affected section(s)) 
+by the automated enrollment process is disabled. The domain default for the failsafe  
+set by a Domain Coordinator can be overridden in a specific course by a Course Coordinator. 
 \end{itemize}
 
 Auto-enrollment settings for each course consist of items set by a
Index: loncom/html/adm/help/tex/Course_Automated_Enrollment.tex
diff -u loncom/html/adm/help/tex/Course_Automated_Enrollment.tex:1.11 loncom/html/adm/help/tex/Course_Automated_Enrollment.tex:1.12
--- loncom/html/adm/help/tex/Course_Automated_Enrollment.tex:1.11	Tue Feb 25 20:31:51 2014
+++ loncom/html/adm/help/tex/Course_Automated_Enrollment.tex	Sun Jul 24 14:35:45 2016
@@ -36,6 +36,15 @@
 appears in the institutional roster when auto-enrollment is run. This
 automatic migration can be prevented for individual students by locking
 the status type.
+\item Zero enrollment failsafe: When enrollment comes from more than one institutional
+course section (including cross-listing), there is a possibility that
+institutional data retrieval might succeed for some, but not all sections.
+In order to avoid expiring student roles in sections for which institutional
+enrollment data could not be retrieved, a failsafe value can be set.  When the
+existing enrollment in a LON-CAPA course section exceeds that failsafe value (an integer),
+dropping of existing students in the affected section(s)) by automated enrollment
+update is disabled. A failsafe value set in a course will override a default value 
+set for the domain.
 \end{itemize}
 
 


More information about the LON-CAPA-cvs mailing list