[LON-CAPA-cvs] cvs: loncom /interface selfenroll.pm

raeburn raeburn@source.lon-capa.org
Thu, 05 Feb 2009 12:27:21 -0000


This is a MIME encoded message

--raeburn1233836841
Content-Type: text/plain

raeburn		Thu Feb  5 12:27:21 2009 EDT

  Modified files:              
    /loncom/interface	selfenroll.pm 
  Log:
  - Bug 5558.
    - Enforce enrollment limits (if set); new routine: &enrollment_limit_check()
    - If self-enrollment requires approval: 
       - store new requests in a queue
       - send messages to Course Coordinators on the Self-enrollment approvals notification list.  New routine: &store_selfenroll_request().
    - New routine: &send_notification() handles sending of messages about new self-enrollment requests requiring approval, and decisions made on pending requests.  
  
  
--raeburn1233836841
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20090205122721.txt"

Index: loncom/interface/selfenroll.pm
diff -u loncom/interface/selfenroll.pm:1.14 loncom/interface/selfenroll.pm:1.15
--- loncom/interface/selfenroll.pm:1.14	Wed Jul 30 16:25:35 2008
+++ loncom/interface/selfenroll.pm	Thu Feb  5 12:27:21 2009
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Allow users to self-enroll in a course
 #
-# $Id: selfenroll.pm,v 1.14 2008/07/30 16:25:35 raeburn Exp $
+# $Id: selfenroll.pm,v 1.15 2009/02/05 12:27:21 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -78,20 +78,45 @@
     }
     my ($canenroll,$selfenroll_types,$selfenroll_registered,@cancreate,
         $knownuser,$selfenroll_access_start,$selfenroll_access_end,
-        $selfenroll_section,$selfenroll_future,%curr_role,$cdomdesc);
+        $selfenroll_section,$selfenroll_future,%curr_role,$cdomdesc,
+        $selfenroll_approval,$selfenroll_limit,$selfenroll_cap,
+        $selfenroll_notifylist,$owner);
     $selfenroll_types = $coursehash{'internal.selfenroll_types'};
     $selfenroll_registered =  $coursehash{'internal.selfenroll_registered'};
     $selfenroll_section = $coursehash{'internal.selfenroll_section'};
     $selfenroll_access_start =  $coursehash{'internal.selfenroll_start_access'};
     $selfenroll_access_end =  $coursehash{'internal.selfenroll_end_access'};
+    $selfenroll_limit =  $coursehash{'internal.selfenroll_limit'};
+    $selfenroll_cap = $coursehash{'internal.selfenroll_cap'};
+    $selfenroll_approval = $coursehash{'internal.selfenroll_approval'};
+    $selfenroll_notifylist = $coursehash{'internal.selfenroll_notifylist'};
+    $owner = $coursehash{'internal.courseowner'};
+    my $nospace;
     if ($selfenroll_types ne '') {
         my $start = $coursehash{'internal.selfenroll_start_date'};
         my $end = $coursehash{'internal.selfenroll_end_date'};
         if (($start > 0 && $start < $now) && (($end == 0) || ($end > 0 && $end > $now))) {
-            $canenroll = 1;
+            if (($selfenroll_limit eq 'allstudents') || 
+                ($selfenroll_limit eq 'selfenroll')) {
+                $nospace = 
+                    &enrollment_limit_check($selfenroll_limit,$selfenroll_cap,
+                                            $cdom,$cnum);
+                if (!$nospace) {
+                    $canenroll = 1; 
+                }
+            } else {
+                $canenroll = 1;
+            }
         } elsif (($end == 0) || ($end > 0 && $end > $now)) {
             if ($start > $now) {
-                $selfenroll_future = &Apache::lonlocal::locallocaltime($start);
+                if (($selfenroll_limit eq 'allstudents') ||
+                    ($selfenroll_limit eq 'selfenroll')) {
+                    $nospace = 
+                        &enrollment_limit_check($selfenroll_limit,$cdom,$cnum);
+                }
+                if (!$nospace) {
+                    $selfenroll_future = &Apache::lonlocal::locallocaltime($start);
+                }
             }
         }
     }
@@ -100,6 +125,14 @@
         $r->print('<h3>'.&mt('Self-enrollment unavailable').'</h3><span class="LC_warning">'.
                   &mt('Self-enrollment is not currently available for this course.').
                   '</span><br /><br />');
+        if ($nospace) {
+            if ($selfenroll_limit eq 'allstudents') {
+                $r->print(&mt('The enrollment limit of [quant,_1,student] has been reached.',$selfenroll_cap));
+            } else {
+                $r->print(&mt('The enrollment limit of [quant,_1,self-enrolled student] has been reached.',$selfenroll_cap));
+
+            }
+        } 
         if ($selfenroll_types ne '') {
             if ($selfenroll_future ne '') {
                 if ($selfenroll_types eq '*') {
@@ -190,7 +223,8 @@
         }
         &process_self_enroll($r,$cdom,$cnum,$selfenroll_types,$selfenroll_registered,
                              $selfenroll_access_start,$selfenroll_access_end,
-                             $selfenroll_section,$now);
+                             $selfenroll_section,$now,$selfenroll_approval,
+                             $selfenroll_notifylist,$owner);
     } elsif ($env{'form.phase'} eq 'login') {
         my $submit_text = &mt('Log in');
         $r->print('<h3>'.&mt('Log-in to LON-CAPA').'</h3>');
@@ -282,6 +316,28 @@
     return OK;
 }
 
+sub enrollment_limit_check {
+    my ($selfenroll_limit,$selfenroll_cap,$cdom,$cnum) = @_;
+    my $nospace = 0;
+    my (%idx,%stucount);
+    my $classlist = &Apache::loncoursedata::get_classlist($cdom,$cnum);
+    $idx{'type'} = &Apache::loncoursedata::CL_TYPE();
+    $idx{'status'} = &Apache::loncoursedata::CL_STATUS();
+    while (my ($student,$data) = each(%$classlist)) {
+        if (($data->[$idx{'status'}] eq 'Active') ||
+            ($data->[$idx{'status'}] eq 'Future')) {
+            if ($data->[$idx{'type'}] eq 'selfenroll') {
+                $stucount{'selfenroll'} ++;
+            }
+            $stucount{'allstudents'} ++;
+        }
+    }
+    if ($stucount{$selfenroll_limit} >= $selfenroll_cap) {
+        $nospace = 1;
+    }
+    return $nospace;
+}
+
 sub page_header {
     my ($r,$courseid,$js,$desc) = @_;
     my $start_page =
@@ -357,7 +413,8 @@
 
 sub process_self_enroll {
     my ($r,$cdom,$cnum,$selfenroll_types,$selfenroll_registered,
-        $selfenroll_access_start,$selfenroll_access_end,$selfenroll_section,$now) = @_;
+        $selfenroll_access_start,$selfenroll_access_end,$selfenroll_section,
+        $now,$selfenroll_approval,$selfenroll_notifylist,$owner) = @_;
     my $udom = $env{'user.domain'};
     my $uname = $env{'user.name'};
     my $selfenroll = 0;
@@ -397,48 +454,55 @@
                 return; 
             } 
         }
-        my $enrollresult = 
-            &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,
-                    undef,undef,$usec,$selfenroll_access_end,$selfenroll_access_start,
-                   'manual',undef,$cdom.'_'.$cnum,$selfenroll);
-        if ($enrollresult eq 'ok') {
-            my (%userroles,%newrole,%newgroups);
-            my $role = 'st';
-            my $area = '/'.$cdom.'/'.$cnum;
-            my $spec = $role.'.'.$area;
-            if ($usec ne '') {
-                $spec .= '/'.$usec;
-                $area .= '/'.$usec;
-            }
-            &Apache::lonnet::standard_roleprivs(\%newrole,$role,$cdom,$spec,$cnum,
-                                                $area);
-            &Apache::lonnet::set_userprivs(\%userroles,\%newrole,%newgroups);
-            $userroles{'user.role.'.$spec} = $selfenroll_access_start.'.'.$selfenroll_access_end;
-            &Apache::lonnet::appenv(\%userroles,[$role,'cm']);
-            $r->print('<h3>'.&mt('Enrollment process complete').'</h3>');
-            if ($selfenroll_access_end && $selfenroll_access_end <= $now) {
-                $r->print(&mt('The end date for access to this course for users who self-enroll has passed.').'<br />'.&mt('Consequently, although a new role was created for you in the course, it is an inactive role which does not provide access to the course.'));
-            } else {
-                $r->print(&mt('Self-enrollment in this course was successful.').'<br />');
-                my $showstart = &Apache::lonlocal::locallocaltime($selfenroll_access_start);
-                my $showend = &Apache::lonlocal::locallocaltime($selfenroll_access_end);
-                if ($selfenroll_access_start && $selfenroll_access_start >$now) {
-                    $r->print(&mt('The start date for access to this course for users who self-enroll has yet to be reached.').'<br />'.&mt('Consequently, although a new role was created for you in the course, you will not be able to select this role until [_1].',$showstart));
+        if ($selfenroll_approval) {
+            my $outcome = 
+                &store_selfenroll_request($udom,$uname,$usec,$cdom,$cnum,
+                                          $selfenroll_notifylist,$owner);
+            $r->print($outcome);
+        } else {
+            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);
+            if ($enrollresult eq 'ok') {
+                my (%userroles,%newrole,%newgroups);
+                my $role = 'st';
+                my $area = '/'.$cdom.'/'.$cnum;
+                my $spec = $role.'.'.$area;
+                if ($usec ne '') {
+                    $spec .= '/'.$usec;
+                    $area .= '/'.$usec;
+                }
+                &Apache::lonnet::standard_roleprivs(\%newrole,$role,$cdom,$spec,$cnum,
+                                                    $area);
+                &Apache::lonnet::set_userprivs(\%userroles,\%newrole,%newgroups);
+                $userroles{'user.role.'.$spec} = $selfenroll_access_start.'.'.$selfenroll_access_end;
+                &Apache::lonnet::appenv(\%userroles,[$role,'cm']);
+                $r->print('<h3>'.&mt('Enrollment process complete').'</h3>');
+                if ($selfenroll_access_end && $selfenroll_access_end <= $now) {
+                    $r->print(&mt('The end date for access to this course for users who self-enroll has passed.').'<br />'.&mt('Consequently, although a new role was created for you in the course, it is an inactive role which does not provide access to the course.'));
                 } else {
-                    my $newrole = 'st./'.$cdom.'/'.$cnum;
-                    if ($usec ne '') {
-                        $newrole .= '/'.$usec;
+                    $r->print(&mt('Self-enrollment in this course was successful.').'<br />');
+                    my $showstart = &Apache::lonlocal::locallocaltime($selfenroll_access_start);
+                    my $showend = &Apache::lonlocal::locallocaltime($selfenroll_access_end);
+                    if ($selfenroll_access_start && $selfenroll_access_start >$now) {
+                        $r->print(&mt('The start date for access to this course for users who self-enroll has yet to be reached.').'<br />'.&mt('Consequently, although a new role was created for you in the course, you will not be able to select this role until [_1].',$showstart));
+                    } else {
+                        my $newrole = 'st./'.$cdom.'/'.$cnum;
+                        if ($usec ne '') {
+                            $newrole .= '/'.$usec;
+                        }
+                        my $rolelink = &jump_to_role($newrole);
+                        $r->print(&mt('Your new role is available immediately, and will provide access to the course until [_1].',$showend).'<br /><br />'."\n".
+                                 $rolelink); 
                     }
-                    my $rolelink = &jump_to_role($newrole);
-                    $r->print(&mt('Your new role is available immediately, and will provide access to the course until [_1].',$showend).'<br /><br />'."\n".
-                             $rolelink); 
                 }
-            }
-        } else {
-            $r->print('<h3>'.&mt('Enrollment incomplete').'</h3>'.
-                      &mt('Self-enrollment in this course failed.'));
-            if ($enrollresult ne '') {
-                $r->print('<span class="LC_error">'.$enrollresult.'</span>');
+            } else {
+                $r->print('<h3>'.&mt('Enrollment incomplete').'</h3>'.
+                          &mt('Self-enrollment in this course failed.'));
+                if ($enrollresult ne '') {
+                    $r->print('<span class="LC_error">'.$enrollresult.'</span>');
+                }
             }
         }
     } else {
@@ -470,6 +534,143 @@
     return $selfenroll;
 }
 
+sub store_selfenroll_request {
+    my ($udom,$uname,$usec,$cdom,$cnum,$selfenroll_notifylist,$owner) = @_;
+    my $namespace = 'selfenrollrequests';
+    my $output;
+    my $now = time;
+    my %existing = 
+        &Apache::lonnet::get($namespace,[$uname.':'.$udom],$cdom,$cnum);
+    if ($existing{$uname.':'.$udom}) {
+        my ($timestamp,$sec) = split(/:/,$existing{$uname.':'.$udom});
+        $output = &mt('A self-enrollment request already exists for you for this course.').'<br />'.&mt('Your earlier request was submitted: [_1] and remains in a queue awaiting action by a Course Coordinator.',&Apache::lonlocal::locallocaltime($timestamp));
+    } else {
+        my %selfenroll = (
+                            $uname.':'.$udom => $now.':'.$usec,
+                         );
+        my $putresult = &Apache::lonnet::put($namespace,\%selfenroll,$cdom,$cnum);
+        if ($putresult eq 'ok') {
+            $output = &mt('Your request for self-enrollment has been recorded.').'<br />'.
+                      &mt('A message will be sent to your LON-CAPA account when the course coordinator takes action on your request').'<br />';
+            my %emails = &Apache::loncommon::getemails($uname,$udom);
+            if (($emails{'permanentemail'} ne '') || ($emails{'notification'} ne '')) {
+                my $address = $emails{'permanentemail'};
+                if ($address eq '') {
+                    $address = $emails{'notification'};
+                }
+                $output.= &mt('An e-mail will also be sent to: [_1] when this occurs.',$address);
+            }
+            if ($selfenroll_notifylist) {
+                my $fullname = &Apache::loncommon::plainname($uname,$udom);
+                my %courseinfo = &Apache::lonnet::coursedescription($cdom.'_'.$cnum);
+                my $coursedesc = $courseinfo{'description'};
+                &send_notification($selfenroll_notifylist,$fullname,$cdom.
+                                   '_'.$cnum,$coursedesc,$now,'request',$owner);
+            }
+        } else {
+            $output = '<span class="LC_error">'.&mt('An error occurred when recording your request.').'</span>';
+
+        }
+    }
+    return $output;
+}
+
+sub send_notification {
+    my ($notifylist,$textstr,$cid,$coursedesc,$timestamp,$context,$sender,
+        $approvedlist,$rejectedlist) = @_;
+# FIXME locallocaltime needs to be able to take $sender_lh as an argument
+#       so this can be localized to the recipients date display format/time zone 
+    $timestamp =&Apache::lonlocal::locallocaltime($timestamp);
+    my $msgcc;
+    my ($rawsubj,@rawmsg,$subject,$message,$namelink);
+    $namelink = &Apache::loncommon::aboutmewrapper(
+                &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'}));
+    if ($context eq 'managers') {
+        $rawsubj = 'Self-enrollment requests processed';
+        push(@rawmsg,{
+                      mt => 'Enrollment requests in the following course: [_1] have been processed.',
+                      args => [$coursedesc],
+                     });
+    } elsif ($context eq 'enroller') {
+        $rawsubj = 'Enrollment request';
+        push(@rawmsg,{
+                      mt  => 'Your request for enrollment in the following course: [_1], requested on [_2], has been reviewed by a Course Coordinator.',
+                      args => [$coursedesc,$timestamp],
+                     });
+        if (ref($textstr) eq 'ARRAY') {
+            push(@rawmsg,@{$textstr});
+        }
+    } else {
+        $rawsubj = 'Self-enrollment request';
+        push(@rawmsg,{
+                      mt  => 'Enrollment in the following course: [_1] was requested by [_2] on [_3].',
+                      args => [$coursedesc,$textstr,$timestamp],
+                     },
+                     {
+                      mt =>'As Course Coordinator, use Main Menu -> Manage Couse Users -> "Enrollment Requests" to display a list of pending enrollment requests which you can either approve or reject.'
+                     });
+    }
+    my @to_notify = split(/,/,$notifylist);
+    my $numsent = 0;
+    my @recusers;
+    my @recudoms;
+    foreach my $cc (@to_notify) {
+        my ($ccname,$ccdom) = split(/:/,$cc);
+        if (!exists($msgcc->{$ccname.':'.$ccdom})) {
+            push(@recusers,$ccname);
+            push(@recudoms,$ccdom);
+            $msgcc->{$ccname.':'.$ccdom}='';
+            $numsent ++;
+        }
+    }
+    my %reciphash = (
+                     cc => $msgcc,
+    );
+    my ($uname,$udom);
+    if ($sender =~ /:/) {
+        ($uname,$udom) = split(/:/,$sender);
+    } else {
+        $uname = $sender;
+        my %courseinfo = &Apache::lonnet::coursedescription($cid);
+        $udom = $courseinfo{'num'};
+    }
+    my %sentmessage;
+    my $stamp = time;
+    my $msgcount = &Apache::lonmsg::get_uniq();
+    my $sender_lh = &Apache::loncommon::user_lang($uname,$udom,$cid);
+    $subject = &Apache::lonlocal::mt_user($sender_lh,$rawsubj);
+    $message = '';
+    foreach my $item (@rawmsg) {
+        if (ref($item) eq 'HASH') {
+            $message .= &Apache::lonlocal::mt_user($sender_lh,$item->{mt},@{$item->{args}})."\n";
+        }
+    }
+    &Apache::lonmsg::process_sent_mail($subject,'',$numsent,$stamp,$uname,$udom,$msgcount,$cid,$$,$message,\@recusers,\@recudoms);
+    my ($recipid,$recipstatus) =
+        &Apache::lonmsg::store_recipients($subject,$uname,$udom,\%reciphash);
+    foreach my $recip (sort(keys(%{$msgcc}))) {
+        my ($ccname,$ccdom) = split(/:/,$recip);
+        my $recip_lh = &Apache::loncommon::user_lang($ccname,$ccdom,$cid);
+        my $subject = &Apache::lonlocal::mt_user($sender_lh,$rawsubj);
+        my $message = '';
+        foreach my $item (@rawmsg) {
+            if (ref($item) eq 'HASH') {
+                $message .= &Apache::lonlocal::mt_user($sender_lh,$item->{mt},
+                                                       @{$item->{args}})."\n";
+            }
+        }
+        if ($context eq 'managers') {
+            if ($approvedlist) {
+                $message .= "\n\n".&Apache::lonlocal::mt_user($sender_lh,'Approved enrollments:')."\n".$approvedlist;
+            }
+            if ($rejectedlist) {
+                $message .= "\n\n".&Apache::lonlocal::mt_user($sender_lh,'Rejected enrollments:')."\n".$rejectedlist;
+            }
+        }
+        my $status = &Apache::lonmsg::user_normal_msg($ccname,$ccdom,$subject,$message,undef,undef,undef,1,\%sentmessage,undef,undef,undef,1,$recipid);
+    }
+}
+
 sub jump_to_role {
     my ($role) = @_;
     my $output = <<"END";

--raeburn1233836841--