--- loncom/interface/lonuserutils.pm	2022/11/23 02:55:37	1.212
+++ loncom/interface/lonuserutils.pm	2023/06/20 14:03:52	1.214
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Utility functions for managing LON-CAPA user accounts
 #
-# $Id: lonuserutils.pm,v 1.212 2022/11/23 02:55:37 raeburn Exp $
+# $Id: lonuserutils.pm,v 1.214 2023/06/20 14:03:52 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -215,12 +215,13 @@ sub get_instdoms {
 sub restricted_dom {
     my ($context,$key,$udom,$uname,$role,$start,$end,$cdom,$cnum,$csec,$credits,
         $process_by,$instdoms,$got_role_approvals,$got_instdoms,$reject,$pending,
-        $notifydc) = @_;
+        $notifydc,$status,$unauthorized,$currqueued) = @_;
     return if ($udom eq $cdom);
     return unless ((ref($process_by) eq 'HASH') && (ref($instdoms) eq 'HASH') &&
                    (ref($got_role_approvals) eq 'HASH') && (ref($got_instdoms) eq 'HASH') &&
                    (ref($reject) eq 'HASH') && (ref($pending) eq 'HASH') &&
-                   (ref($notifydc) eq 'HASH'));
+                   (ref($notifydc) eq 'HASH') && (ref($status) eq 'HASH') &&
+                   (ref($unauthorized) eq 'HASH') && (ref($currqueued) eq 'HASH'));
     my (%approval,@notify,$gotdata,$skip);
     if (ref($got_role_approvals->{$context}) eq 'HASH') {
         if ($got_role_approvals->{$context}{$udom}) {
@@ -255,62 +256,126 @@ sub restricted_dom {
             if (grep(/^\Q$cdom\E$/,@inst)) {
                 if (exists($approval{'instdom'})) {
                     my $rule = $approval{'instdom'};
-                    if ($rule eq 'none') {
-                        $reject->{$key} = {
-                                            cdom  => $cdom,
-                                            cnum  => $cnum,
-                                            csec  => $csec,
-                                            udom  => $udom,
-                                            uname => $uname,
-                                            role  => $role,
-                                          };
-                        $skip = 1;
-                    } elsif (($rule eq 'user') || ($rule eq 'domain')) {
-                        $pending->{$key} = {
-                                             cdom  => $cdom,
-                                             cnum  => $cnum,
-                                             csec  => $csec,
-                                             udom  => $udom,
-                                             uname => $uname,
-                                             role  => $role,
-                                             start => $start,
-                                             end   => $end,
-                                             adj   => $rule,
-                                           };
-                        if (($role eq 'st') && ($credits ne '')) {
-                            $pending->{$key}->{'credits'} = $credits;
+                    if (($rule eq 'none') || ($rule eq 'user') || ($rule eq 'domain')) {
+                        my ($id,$currstatus,$curradj) = &get_othdomreq_status($key,$uname,$udom,$role,$cdom,$cnum,$csec);
+                        if (($currstatus ne '') && ($curradj eq $rule)) {
+                            $status->{$key}->{$uname.':'.$udom} = $currstatus;
+                        }
+                        if ($rule eq 'none') {
+                             $reject->{$key}->{$uname.':'.$udom} = {
+                                                                     cdom  => $cdom,
+                                                                     cnum  => $cnum,
+                                                                     csec  => $csec,
+                                                                     udom  => $udom,
+                                                                     uname => $uname,
+                                                                     role  => $role,
+                                                                   };
+                            $skip = 1;
+                        } elsif (($rule eq 'user') || ($rule eq 'domain')) {
+                            if ($curradj eq $rule) {
+                                unless ($currstatus eq 'approved') {
+                                    if ($currstatus eq 'rejected') {
+                                        $unauthorized->{$key}->{$uname.':'.$udom} = {
+                                                                                      cdom  => $cdom,
+                                                                                      cnum  => $cnum,
+                                                                                      csec  => $csec,
+                                                                                      udom  => $udom,
+                                                                                      uname => $uname,
+                                                                                      role  => $role,
+                                                                                    };
+                                    } elsif ($currstatus eq 'pending') {
+                                        $currqueued->{$key}->{$uname.':'.$udom} = {
+                                                                                    cdom  => $cdom,
+                                                                                    cnum  => $cnum,
+                                                                                    csec  => $csec,
+                                                                                    udom  => $udom,
+                                                                                    uname => $uname,
+                                                                                    role  => $role,
+                                                                                    adj   => $rule,
+                                                                       };
+                                    }
+                                    $skip = 1;
+                                }
+                            } else {
+                                $pending->{$key}->{$uname.':'.$udom} = {
+                                                                         cdom  => $cdom,
+                                                                         cnum  => $cnum,
+                                                                         csec  => $csec,
+                                                                         udom  => $udom,
+                                                                         uname => $uname,
+                                                                         role  => $role,
+                                                                         start => $start,
+                                                                         end   => $end,
+                                                                         adj   => $rule,
+                                                                       };
+                                if (($role eq 'st') && ($credits ne '')) {
+                                    $pending->{$key}->{$uname.':'.$udom}->{'credits'} = $credits;
+                                }
+                                $skip = 1;
+                            }
                         }
-                        $skip = 1;
                     }
                 }
             } elsif (exists($approval{'extdom'})) {
                 my $rule = $approval{'extdom'};
-                if ($rule eq 'none') {
-                    $reject->{$key} = {
-                                        cdom  => $cdom,
-                                        cnum  => $cnum,
-                                        csec  => $csec,
-                                        udom  => $udom,
-                                        uname => $uname,
-                                        role  => $role,
-                                      };
-                    $skip = 1;
-                } elsif (($rule eq 'user') || ($rule eq 'domain')) {
-                    $pending->{$key} = {
-                                         cdom  => $cdom,
-                                         cnum  => $cnum,
-                                         csec  => $csec,
-                                         udom  => $udom,
-                                         uname => $uname,
-                                         role  => $role,
-                                         start => $start,
-                                         end   => $end,
-                                         adj   => $rule,
-                                       };
-                    if (($role eq 'st') && ($credits ne '')) {
-                        $pending->{$key}->{'credits'} = $credits;
+                if (($rule eq 'none') || ($rule eq 'user') || ($rule eq 'domain')) {
+                    my ($id,$currstatus,$curradj) = &get_othdomreq_status($key,$uname,$udom,$role,$cdom,$cnum,$csec);
+                    if (($currstatus ne '') && ($curradj eq $rule)) {
+                        $status->{$key}->{$uname.':'.$udom} = $currstatus;
+                    }
+                    if ($rule eq 'none') {
+                        $reject->{$key}->{$uname.':'.$udom} = {
+                                                                cdom  => $cdom,
+                                                                cnum  => $cnum,
+                                                                csec  => $csec,
+                                                                udom  => $udom,
+                                                                uname => $uname,
+                                                                role  => $role,
+                                                              };
+                        $skip = 1;
+                    } elsif (($rule eq 'user') || ($rule eq 'domain')) {
+                        if ($curradj eq $rule) {
+                            unless ($currstatus eq 'approved') {
+                                if ($currstatus eq 'rejected') {
+                                    $unauthorized->{$key}->{$uname.':'.$udom} = {
+                                                                                  cdom  => $cdom,
+                                                                                  cnum  => $cnum,
+                                                                                  csec  => $csec,
+                                                                                  udom  => $udom,
+                                                                                  uname => $uname,
+                                                                                  role  => $role,
+                                                                                };
+                                } elsif ($currstatus eq 'pending') {
+                                    $currqueued->{$key}->{$uname.':'.$udom} = {
+                                                                                cdom  => $cdom,
+                                                                                cnum  => $cnum,
+                                                                                csec  => $csec,
+                                                                                udom  => $udom,
+                                                                                uname => $uname,
+                                                                                role  => $role,
+                                                                                adj   => $rule,
+                                                                       };
+                                }
+                                $skip = 1;
+                            }
+                        } else {
+                            $pending->{$key}->{$uname.':'.$udom} = {
+                                                                     cdom  => $cdom,
+                                                                     cnum  => $cnum,
+                                                                     csec  => $csec,
+                                                                     udom  => $udom,
+                                                                     uname => $uname,
+                                                                     role  => $role,
+                                                                     start => $start,
+                                                                     end   => $end,
+                                                                     adj   => $rule,
+                                                                   };
+                            if (($role eq 'st') && ($credits ne '')) {
+                                $pending->{$key}->{$uname.':'.$udom}->{'credits'} = $credits;
+                            }
+                            $skip = 1;
+                        }
                     }
-                    $skip = 1;
                 }
             }
         }
@@ -318,53 +383,130 @@ sub restricted_dom {
     return $skip;
 }
 
+sub get_othdomreq_status {
+    my ($key,$uname,$udom,$role,$cdom,$cnum,$csec) = @_;
+    my $id = $uname.':'.$udom.':'.$role; 
+    my ($dbnum,$currstatus,$curradj);
+    if (($role eq 'ca') || ($role eq 'aa')) {
+        $dbnum = $cnum;
+    } elsif ($key eq $cdom.'_'.$role) {
+        $dbnum = &Apache::lonnet::get_domainconfiguser($cdom);
+    } else {
+        $id .= ':'.$csec;
+        $dbnum = $cnum;
+    }
+    my $statusid = 'status&'.$id;
+    my %curr = &Apache::lonnet::get('nohist_othdomqueued',[$id,$statusid],$cdom,$dbnum);
+    if (ref($curr{$id}) eq 'HASH') {
+        $curradj = $curr{$id}{'adj'};
+    }
+    $currstatus = $curr{$statusid};
+    return ($id,$currstatus,$curradj);
+}
+
 sub print_roles_rejected {
-    my ($context,$reject) = @_;
-    return unless (ref($reject) eq 'HASH');
+    my ($context,$reject,$unauthorized) = @_;
+    return unless ((ref($reject) eq 'HASH') || (ref($unauthorized) eq 'HASH'));
     my $output;
     if (keys(%{$reject}) > 0) {
         $output = '<p class="LC_warning">'.
                   &mt("The following roles could not be assigned because the user is from another domain, and that domain's policies disallow it").'<ul>';
         foreach my $key (sort(keys(%{$reject}))) {
             if (ref($reject->{$key}) eq 'HASH') {
-                my ($crstype,$role,$cdom,$cnum,$title);
-                $role = $reject->{$key}{'role'};
-                $cdom = $reject->{$key}{'cdom'};
-                $cnum = $reject->{$key}{'cnum'};
-                if ($context eq 'domain') {
-                    if (&Apache::lonnet::is_course($cdom,$cnum)) {
-                        my %coursedata = &Apache::lonnet::coursedescription($cdom.'_'.$cnum);
-                        $crstype = $coursedata{'type'};
-                        $title = $coursedata{'description'};
-                    } elsif (($role eq 'ca') || ($role eq 'aa')) {
-                        $title = &Apache::loncommon::plainname($cnum,$cdom);
-                    }
-                } elsif ($context eq 'course') {
-                    $crstype = &Apache::loncommon::course_type();
-                }
-                my $plainrole = &Apache::lonnet::plaintext($reject->{$key}{'role'},$crstype);
-                $output .= '<li>'.&mt('User: [_1]',$reject->{$key}{'uname'}).' | '.
-                                  &mt('Domain: [_1]',$reject->{$key}{'udom'}).' | '.
-                                  &mt('Role: [_1]',$plainrole);
-                if ($crstype) {
-                    $output .= ' | '.&mt('Section: [_1]',$reject->{$key}{'csec'});
-                } elsif (($context eq 'domain') && (($role eq 'ca') || ($role eq 'aa'))) {
-                    $output .= ' | '.&mt('Authoring Space belonging to: [_1]',$title);
-                }
-                if (($context eq 'domain') && ($crstype)) {
-                    $output .= ' | '.&mt("$crstype: [_1]",$title);
+                foreach my $user (sort(keys(%{$reject->{$key}}))) {
+                    if (ref($reject->{$key}->{$user}) eq 'HASH') {
+                        my ($crstype,$role,$cdom,$cnum,$csec,$title,$plainrole);
+                        $role = $reject->{$key}->{$user}{'role'};
+                        $cdom = $reject->{$key}->{$user}{'cdom'};
+                        $cnum = $reject->{$key}->{$user}{'cnum'};
+                        $csec = $reject->{$key}->{$user}{'csec'};
+                        if (($context eq 'domain') && ($cnum ne '')) {
+                            if (($role eq 'ca') || ($role eq 'aa')) {
+                                $title = &Apache::loncommon::plainname($cnum,$cdom);
+                            } else {
+                                if (&Apache::lonnet::is_course($cdom,$cnum)) {
+                                    my %coursedata = &Apache::lonnet::coursedescription($cdom.'_'.$cnum);
+                                    $crstype = $coursedata{'type'};
+                                    $title = $coursedata{'description'};
+                                }
+                            }
+                        } elsif ($context eq 'course') {
+                            $crstype = &Apache::loncommon::course_type();
+                        }
+                        my $plainrole = &Apache::lonnet::plaintext($role,$crstype);
+                        $output .= '<li>'.&mt('User: [_1]',$reject->{$key}->{$user}{'uname'}).' | '.
+                                          &mt('Domain: [_1]',$reject->{$key}->{$user}{'udom'}).' | '.
+                                          &mt('Role: [_1]',$plainrole);
+                        if ($crstype) {
+                            if ($csec ne'') {
+                                $output .= ' | '.&mt('Section: [_1]',$csec);
+                            }
+                        } elsif (($context eq 'domain') && (($role eq 'ca') || ($role eq 'aa'))) {
+                            $output .= ' | '.&mt('Authoring Space belonging to: [_1]',$title);
+                                                
+                        }
+                        if (($context eq 'domain') && ($crstype)) {
+                            $output .= ' | '.&mt("$crstype: [_1]",$title);
+                        }
+                        $output .= '</li>';
+                    }
                 }
-                $output .= '</li>';
             }
         }
         $output .= '</ul></p>';
     }
+    if (keys(%{$unauthorized}) > 0) {
+        $output = '<p class="LC_warning">'.
+                  &mt("The following roles could not be assigned because the user is from another domain, and that domain's policies require approval by the user themselves or by a domain coordinator in that domain, and approval has been withheld.").'<ul>';
+        foreach my $key (sort(keys(%{$unauthorized}))) {
+            if (ref($unauthorized->{$key}) eq 'HASH') {
+                foreach my $user (sort(keys(%{$unauthorized->{$key}}))) {
+                    if (ref($unauthorized->{$key}->{$user}) eq 'HASH') {
+                        my ($crstype,$role,$cdom,$cnum,$csec,$title,$plainrole);
+                        $role = $unauthorized->{$key}->{$user}{'role'};
+                        $cdom = $unauthorized->{$key}->{$user}{'cdom'};
+                        $cnum = $unauthorized->{$key}->{$user}{'cnum'};
+                        $csec = $unauthorized->{$key}->{$user}{'csec'};
+                        if (($context eq 'domain') && ($cnum ne '')) {
+                            if (($role eq 'ca') || ($role eq 'aa')) {
+                                $title = &mt('Authoring Space belonging to: [_1]',
+                                             &Apache::loncommon::plainname($cnum,$cdom));
+                            } else {
+                                if (&Apache::lonnet::is_course($cdom,$cnum)) {
+                                    my %coursedata = &Apache::lonnet::coursedescription($cdom.'_'.$cnum);
+                                    $crstype = $coursedata{'type'};
+                                    $title = &mt("$crstype: [_1]",$coursedata{'description'});
+                                }
+                            }
+                        } elsif ($context eq 'course') {
+                            $crstype = &Apache::loncommon::course_type();
+                        }
+                        $plainrole = &Apache::lonnet::plaintext($role,$crstype);
+                        $output .= '<li>'.&mt('User: [_1]',$unauthorized->{$key}->{$user}{'uname'}).' | '.
+                                          &mt('Domain: [_1]',$unauthorized->{$key}->{$user}{'udom'}).' | '.
+                                          &mt('Role: [_1]',$plainrole);
+                        if ($crstype) {
+                            if ($csec ne'') {
+                                $output .= ' | '.&mt('Section: [_1]',$csec);
+                            }
+                        }
+                        if ($title ne '') {
+                            $output .= ' | '.$title;
+                        }
+                        $output .= '</li>';
+                    }
+                }
+            }
+        }
+        $output .= '</ul></p>'; 
+    }
     return $output;
 }
 
 sub print_roles_queued {
-    my ($context,$pending,$notifydc) = @_;
-    return unless ((ref($pending) eq 'HASH') && (ref($notifydc) eq 'HASH'));
+    my ($context,$pending,$notifydc,$currqueued) = @_;
+    return unless ((ref($pending) eq 'HASH') && (ref($notifydc) eq 'HASH') &&
+                   (ref($currqueued) eq 'HASH'));
     my $output;
     if (keys(%{$pending}) > 0) {
         my $now = time;
@@ -374,91 +516,108 @@ sub print_roles_queued {
         my $requester = $env{'user.name'}.':'.$env{'user.domain'};
         foreach my $key (sort(keys(%{$pending}))) {
             if (ref($pending->{$key}) eq 'HASH') {
-                my $role = $pending->{$key}{'role'};
-                my $uname = $pending->{$key}{'uname'};
-                my $udom = $pending->{$key}{'udom'};
-                my $csec = $pending->{$key}{'csec'};
-                my $cdom = $pending->{$key}{'cdom'};
-                my $cnum = $pending->{$key}{'cnum'};
-                my $adj = $pending->{$key}{'adj'};
-                my $start = $pending->{$key}{'start'};
-                my $end = $pending->{$key}{'end'};
-                my $credits = $pending->{$key}{'credits'};
-                my $now = time;
-                my ($crstype,$title);
-                if ($context eq 'course') {
-                    $crstype = &Apache::loncommon::course_type();
-                } elsif ($context eq 'domain') {
-                    if (&Apache::lonnet::is_course($cdom,$cnum)) {
-                        my %coursedata = &Apache::lonnet::coursedescription($cdom.'_'.$cnum);
-                        $crstype = $coursedata{'type'};
-                        $title = $coursedata{'description'};
-                    } elsif (($role eq 'ca') || ($role eq 'aa')) {
-                        $title = &Apache::loncommon::plainname($cnum,$cdom);
-                    }
-                }
-                my $plainrole = &Apache::lonnet::plaintext($role,$crstype);
-                my $extent = "/$cdom/$cnum";
-                $output .= '<li>'.&mt('User: [_1]',$uname).' | '.
-                                  &mt('Domain: [_1]',$udom).' | '.
-                                  &mt('Role: [_1]',$plainrole).' | ';
-                if ($crstype) {
-                    if ($csec ne '') {
-                        $output .= &mt('Section: [_1]',$csec).' | ';
-                        $extent .= "/$csec";
-                    }
-                }
-                if ($adj eq 'user') {
-                    $output .= '<br />'.&mt('Message sent to user for approval');
-                    $touser{$uname.':'.$udom}{$extent.':'.$role} = {
-                                                                     timestamp => $now,
-                                                                     requester => $requester,
-                                                                     start     => $start,
-                                                                     end       => $end,
-                                                                     credits   => $credits,
-                                                                     context   => $context,
-                                                                   };
-                } elsif ($adj eq 'domain') {
-                    $output .= '<br />'.&mt("Message sent to user's domain coordinator for approval");
-                    $todom{$udom}{$uname.':'.$extent.':'.$role} = {
-                                                                    timestamp => $now,
-                                                                    requester => $requester,
-                                                                    start     => $start,
-                                                                    end       => $end,
-                                                                    credits   => $credits,
-                                                                    context   => $context,
-                                                                  };
-                }
-                $output .= '</li>';
-                my $id = $uname.':'.$udom.':'.$role;
-                if (($context eq 'course') || ($crstype)) {
-                    $id .= ':'.$csec;
-                    $crsqueue{$cdom.'_'.$cnum}{$id} = {
-                                                        timestamp => $now,
-                                                        requester => $requester,
-                                                        adj       => $adj,
-                                                      };
-                } elsif (($context eq 'author') ||
-                         (($context eq 'domain') && (($role eq 'ca') || ($role eq 'aa')))) {
-                    $caqueue{$cnum.':'.$cdom}{$id} = {
-                                                        timestamp => $now,
-                                                        requester => $requester,
-                                                        adj       => $adj,
-                                                      };
-                } elsif ($context eq 'domain') {
-                    $domqueue{$id} = {
-                                        timestamp => $now,
-                                        requester => $requester,
-                                        adj       => $adj,
-                                     };
+                foreach my $user (sort(keys(%{$pending->{$key}}))) {
+                    if (ref($pending->{$key}->{$user}) eq 'HASH') {
+                        my $role = $pending->{$key}->{$user}{'role'};
+                        my $uname = $pending->{$key}->{$user}{'uname'};
+                        my $udom = $pending->{$key}->{$user}{'udom'};
+                        my $csec = $pending->{$key}->{$user}{'csec'};
+                        my $cdom = $pending->{$key}->{$user}{'cdom'};
+                        my $cnum = $pending->{$key}->{$user}{'cnum'};
+                        my $adj = $pending->{$key}->{$user}{'adj'};
+                        my $start = $pending->{$key}->{$user}{'start'};
+                        my $end = $pending->{$key}->{$user}{'end'};
+                        my $credits = $pending->{$key}->{$user}{'credits'};
+                        my $now = time;
+                        my ($crstype,$title,$plainrole,$extent,$id,$status);
+                        if ($context eq 'course') {
+                            $crstype = &Apache::loncommon::course_type();
+                            $title = $env{'course.'.$env{'request.course.id'}.'.description'};
+                        } elsif ($context eq 'domain') {
+                            if (&Apache::lonnet::is_course($cdom,$cnum)) {
+                                my %coursedata = &Apache::lonnet::coursedescription($cdom.'_'.$cnum);
+                                $crstype = $coursedata{'type'};
+                                $title = $coursedata{'description'};
+                            } elsif (($role eq 'ca') || ($role eq 'aa')) {
+                                $title = &Apache::loncommon::plainname($cnum,$cdom);
+                            }
+                        }
+                        $plainrole = &Apache::lonnet::plaintext($role,$crstype);
+                        $extent = "/$cdom/$cnum";
+                        $id = $uname.':'.$udom.':'.$role;
+                        if (($context eq 'course') || ($crstype)) {
+                            $id .= ':'.$csec;
+                        }
+                        $output .= '<li>'.&mt('User: [_1]',$uname).' | '.
+                                          &mt('Domain: [_1]',$udom).' | '.
+                                          &mt('Role: [_1]',$plainrole);
+                        if ($crstype) {
+                            if ($csec ne'') {
+                                $output .= ' | '.&mt('Section: [_1]',$csec);
+                            }
+                        } elsif (($context eq 'domain') && (($role eq 'ca') || ($role eq 'aa'))) {
+                            $output .= ' | '.&mt('Authoring Space belonging to: [_1]',$title);
+                        }
+                        if (($context eq 'domain') && ($crstype)) {
+                            $output .= ' | '.&mt("$crstype: [_1]",$title);
+                        }
+                        if (($crstype) && ($csec ne '')) {
+                            $extent .= "/$csec";
+                        }
+                        if ($adj eq 'user') {
+                            $output .= '<br />'.&mt('Message sent to user for approval');
+                            $touser{$uname.':'.$udom}{'pending:'.$extent.':'.$role} = {
+                                                                                        timestamp => $now,
+                                                                                        requester => $requester,
+                                                                                        start     => $start,
+                                                                                        end       => $end,
+                                                                                        credits   => $credits,
+                                                                                        context   => $context,
+                                                                                      };
+                        } elsif ($adj eq 'domain') {
+                            $output .= '<br />'.&mt("Message sent to user's domain coordinator for approval");
+                            $todom{$udom}{'pending:'.$uname.':'.$extent.':'.$role} = {
+                                                                                       timestamp => $now,
+                                                                                       requester => $requester,
+                                                                                       start     => $start,
+                                                                                       end       => $end,
+                                                                                       credits   => $credits,
+                                                                                       context   => $context,
+                                                                                     };
+                        }
+                        $output .= '</li>';
+                        if (($context eq 'course') || ($crstype)) {
+                            $crsqueue{$cdom.'_'.$cnum}{$id} = {
+                                                                timestamp => $now,
+                                                                requester => $requester,
+                                                                adj       => $adj,
+                                                              };
+                            $crsqueue{$cdom.'_'.$cnum}{'status&'.$id} = 'pending';
+                        } elsif (($context eq 'author') ||
+                                 (($context eq 'domain') && (($role eq 'ca') || ($role eq 'aa')))) {
+                            $caqueue{$cnum.':'.$cdom}{$id} = {
+                                                               timestamp => $now,
+                                                               requester => $requester,
+                                                               adj       => $adj,
+                                                             };
+                            $caqueue{$cnum.':'.$cdom}{'status&'.$id} = 'pending';
+                        } elsif ($context eq 'domain') {
+                            $domqueue{$id} = {
+                                               timestamp => $now,
+                                               requester => $requester,
+                                               adj       => $adj,
+                                             };
+                            $domqueue{'status&'.$id} = 'pending';
+                        }
+                    }
                 }
             }
         }
         $output .= '</ul></p>';
         if (keys(%touser)) {
             foreach my $key (keys(%touser)) {
-                my ($uname,$udom) = split(/:/,$touser{$key});
-                if (&Apache::lonnet::put('queuedrolereqs',$touser{$key},$udom,$uname) eq 'ok') {
+                my ($uname,$udom) = split(/:/,$key);
+                if (&Apache::lonnet::put('nohist_queuedrolereqs',$touser{$key},$udom,$uname) eq 'ok') {
                     my $owndomdesc = &Apache::lonnet::domain($udom);
                     &Apache::loncoursequeueadmin::send_selfserve_notification($uname.':'.$udom,
                         '','',$owndomdesc,$now,'othdomroleuser',$requester);
@@ -469,7 +628,7 @@ sub print_roles_queued {
             foreach my $dom (keys(%todom)) {
                 if (ref($todom{$dom}) eq 'HASH') {
                     my $confname = &Apache::lonnet::get_domainconfiguser($dom);
-                    if (&Apache::lonnet::put('queuedrolereqs',$todom{$dom},$dom,$confname) eq 'ok') {
+                    if (&Apache::lonnet::put('nohist_queuedrolereqs',$todom{$dom},$dom,$confname) eq 'ok') {
                         if (ref($notifydc->{$dom}) eq 'ARRAY') {
                             if (@{$notifydc->{$dom}} > 0) {
                                 my $notifylist = join(',',@{$notifydc->{$dom}});
@@ -485,7 +644,7 @@ sub print_roles_queued {
             foreach my $key (keys(%crsqueue)) {
                 my ($cdom,$cnum) = split(/_/,$key);
                 if (ref($crsqueue{$key}) eq 'HASH') {
-                    &Apache::lonnet::put('othdomqueued',$crsqueue{$key},$cdom,$cnum);
+                    &Apache::lonnet::put('nohist_othdomqueued',$crsqueue{$key},$cdom,$cnum);
                 }
             }
         }
@@ -493,15 +652,59 @@ sub print_roles_queued {
             foreach my $key (keys(%caqueue)) {
                 my ($auname,$audom) = split(/:/,$key);
                 if (ref($caqueue{$key}) eq 'HASH') {
-                    &Apache::lonnet::put('othdomqueued',$caqueue{$key},$audom,$auname);
+                    &Apache::lonnet::put('nohist_othdomqueued',$caqueue{$key},$audom,$auname);
                 }
             }
         }
         if (keys(%domqueue)) {
             my $confname = &Apache::lonnet::get_domainconfiguser($env{'request.role.domain'});
-            &Apache::lonnet::put('othdomqueued',\%domqueue,$env{'request.role.domain'},$confname);
+            &Apache::lonnet::put('nohist_othdomqueued',\%domqueue,$env{'request.role.domain'},$confname);
         }
     }
+    if (keys(%{$currqueued}) > 0) {
+        $output = '<p class="LC_warning">'.
+                  &mt("The following role assignments were already queued because the user is from another domain, and that domain's policies require approval by the user themselves or by a domain coordinator in that domain").'<ul>';
+        my $requester = $env{'user.name'}.':'.$env{'user.domain'};
+        foreach my $key (sort(keys(%{$currqueued}))) {
+            if (ref($currqueued->{$key}) eq 'HASH') {
+                foreach my $user (sort(keys(%{$currqueued->{$key}}))) {
+                    if (ref($currqueued->{$key}->{$user}) eq 'HASH') {
+                        my $role = $currqueued->{$key}->{$user}{'role'};
+                        my $csec = $currqueued->{$key}->{$user}{'csec'};
+                        my $cdom = $currqueued->{$key}->{$user}{'cdom'};
+                        my $cnum = $currqueued->{$key}->{$user}{'cnum'};
+                        my ($crstype,$title,$plainrole);
+                        if ($context eq 'course') {
+                            $crstype = &Apache::loncommon::course_type();
+                        } elsif (($context eq 'domain') && ($cnum ne '')) {
+                            if (($role eq 'ca') || ($role eq 'aa')) {
+                                $title = &mt('Authoring Space belonging to: [_1]',
+                                             &Apache::loncommon::plainname($cnum,$cdom));
+                            } elsif (&Apache::lonnet::is_course($cdom,$cnum)) {
+                                my %coursedata = &Apache::lonnet::coursedescription($cdom.'_'.$cnum);
+                                $crstype = $coursedata{'type'};
+                                $title = &mt("$crstype: [_1]",$coursedata{'description'});
+                            }
+                        }
+                        $plainrole = &Apache::lonnet::plaintext($role,$crstype);
+                        $output .= '<li>'.&mt('User: [_1]',$currqueued->{$key}->{$user}{'uname'}).' | '.
+                                          &mt('Domain: [_1]',$currqueued->{$key}->{$user}{'udom'}).' | '.
+                                          &mt('Role: [_1]',$plainrole);
+                        if ($title ne '') {
+                            $output .= ' | '.$title;
+                        }
+                        if ($crstype) {
+                            if ($csec ne '') {
+                                $output .= ' | '.&mt('Section: [_1]',$csec);
+                            }
+                        }
+                        $output .= '</li>';
+                    }
+                }
+            }
+        }
+        $output .= '</ul></p>';
+    }
     return $output;
 }
 
@@ -4720,7 +4923,7 @@ sub upfile_drop_add {
         }
         $r->rflush;
         my (%got_role_approvals,%got_instdoms,%process_by,%instdoms,
-            %pending,%reject,%notifydc);
+            %pending,%reject,%notifydc,%status,%unauthorized,%currqueued);
 
         my %counts = (
                        user => 0,
@@ -5262,7 +5465,7 @@ sub upfile_drop_add {
                             next if (&restricted_dom($context,$item,$userdomain,$username,$role,$startdate,
                                                      $enddate,$crsdom,$crsnum,$sec,$credits,\%process_by,
                                                      \%instdoms,\%got_role_approvals,\%got_instdoms,\%reject,
-                                                     \%pending,\%notifydc));
+                                                     \%pending,\%notifydc,\%status,\%unauthorized,\%currqueued));
                         }
                         &modifystudent($userdomain,$username,$cid,$sec,
                                        $desiredhost,$context);
@@ -5300,7 +5503,8 @@ sub upfile_drop_add {
                                                 next if (&restricted_dom($context,$item,$userdomain,$username,$possrole,
                                                                          $startdate,$enddate,$crsdom,$crsnum,$sec,
                                                                          $credits,\%process_by,\%instdoms,\%got_role_approvals,
-                                                                         \%got_instdoms,\%reject,\%pending,\%notifydc));
+                                                                         \%got_instdoms,\%reject,\%pending,\%notifydc,
+                                                                         \%status,\%unauthorized,\%currqueued));
                                             }
                                             ($userres{$sec},$authres{$sec},$roleres{$sec},$idres{$sec}) =
                                             &modifyuserrole($context,$setting,
@@ -5328,7 +5532,8 @@ sub upfile_drop_add {
                                 $item .= '_'.$possrole;
                                 next if (&restricted_dom($context,$item,$userdomain,$username,$possrole,$startdate,$enddate,
                                                          $crsdom,$crsnum,$singlesec,$credits,\%process_by,\%instdoms,
-                                                         \%got_role_approvals,\%got_instdoms,\%reject,\%pending,\%notifydc));
+                                                         \%got_role_approvals,\%got_instdoms,\%reject,\%pending,\%notifydc,
+                                                         \%status,\%unauthorized,\%currqueued));
                             }
                             ($userresult,$authresult,$roleresult,$idresult) = 
                                 &modifyuserrole($context,$setting,
@@ -5379,11 +5584,11 @@ sub upfile_drop_add {
         }
         $r->print(&print_namespacing_alerts($domain,\%alerts,\%curr_rules));
         $r->print(&passwdrule_alerts($domain,\%showpasswdrules));
-        if (keys(%reject)) {
-            $r->print(&print_roles_rejected($context,\%reject));
+        if ((keys(%reject)) || (keys(%unauthorized))) {
+            $r->print(&print_roles_rejected($context,\%reject,\%unauthorized));
         }
-        if (keys(%pending)) {
-            $r->print(&print_roles_queued($context,\%pending,\%notifydc));
+        if ((keys(%pending)) || (keys(%currqueued))) {
+            $r->print(&print_roles_queued($context,\%pending,\%notifydc,\%currqueued));
         }
         #####################################
         # Display list of students to drop  #
@@ -5579,7 +5784,7 @@ sub update_user_list {
         $crstype = &Apache::loncommon::course_type();
     }
     my (@changelist,%got_role_approvals,%got_instdoms,%process_by,%instdoms,
-        %pending,%reject,%notifydc);
+        %pending,%reject,%notifydc,%status,%unauthorized,%currqueued);
     if ($choice eq 'drop') {
         @changelist = &Apache::loncommon::get_env_multiple('form.droplist');
     } else {
@@ -5697,7 +5902,8 @@ sub update_user_list {
             if ($choice eq 'reenable') {
                 next if (&restricted_dom($context,$id,$udom,$uname,$role,$now,$end,$cdom,$cnum,
                                          $sec,$credits,\%process_by,\%instdoms,\%got_role_approvals,
-                                         \%got_instdoms,\%reject,\%pending,\%notifydc));
+                                         \%got_instdoms,\%reject,\%pending,\%notifydc,
+                                         \%status,\%unauthorized,\%currqueued));
                 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,$instsec);
                 } else {
@@ -5708,7 +5914,8 @@ sub update_user_list {
             } elsif ($choice eq 'activate') {
                 next if (&restricted_dom($context,$id,$udom,$uname,$role,$now,$end,$cdom,$cnum,
                                          $sec,$credits,\%process_by,\%instdoms,\%got_role_approvals,
-                                         \%got_instdoms,\%reject,\%pending,\%notifydc));
+                                         \%got_instdoms,\%reject,\%pending,\%notifydc,
+                                         \%status,\%unauthorized,\%currqueued));
                 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,$instsec);
                 } else {
@@ -5718,7 +5925,8 @@ sub update_user_list {
             } elsif ($choice eq 'chgdates') {
                 next if (&restricted_dom($context,$id,$udom,$uname,$role,$start,$end,$cdom,$cnum,
                                          $sec,$credits,\%process_by,\%instdoms,\%got_role_approvals,
-                                         \%got_instdoms,\%reject,\%pending,\%notifydc));
+                                         \%got_instdoms,\%reject,\%pending,\%notifydc,
+                                         \%status,\%unauthorized,\%currqueued));
                 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,$instsec);
                 } else {
@@ -5928,11 +6136,11 @@ sub update_user_list {
             $r->print(&make_dates_default($startdate,$enddate,$context,$crstype));
         }
     }
-    if (keys(%reject)) {
-        $r->print(&print_roles_rejected($context,\%reject));
+    if ((keys(%reject)) || (keys(%unauthorized))) {
+        $r->print(&print_roles_rejected($context,\%reject,\%unauthorized));
     }
-    if (keys(%pending)) {
-        $r->print(&print_roles_queued($context,\%pending,\%notifydc));
+    if ((keys(%pending)) || (keys(%currqueued))) {
+        $r->print(&print_roles_queued($context,\%pending,\%notifydc,\%currqueued));
     }
     my $linktext = &mt('Display User Lists');
     if ($choice eq 'drop') {