peterm
committed
on 14 Apr 04
fixing ticket 52. Making enroll_user proc check whether user is already is enrolled and just return if he is.
openacs-4/.../tcl/template-procs.tcl (+16 -6)
941 941     array set row [list]
942 942     foreach role_id [array names roles] {
943 943         array unset one_role
944 944         array set one_role $roles($role_id)
945 945
946 946         # Get the number of already assigned users in the role and
947 947         # figure out if there are empty slots
948 948         set users_already_in_case [db_string n_users_already_in_case {
949 949             select count(*)
950 950             from workflow_case_role_party_map wcrpm
951 951             where wcrpm.case_id = :case_id
952 952               and wcrpm.role_id = :role_id
953 953         }]
954 954          
955 955         if { [expr $users_already_in_case >= $one_role(users_per_case)] } {
956 956             set n_users_to_assign 0
957 957         } else {
958 958             set n_users_to_assign [expr $one_role(users_per_case) - $users_already_in_case]
959 959         }
960 960        
961           #ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - beginning of role loop role_id=$role_id n_users_to_assign=$n_users_to_assign"
  961         #ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - beginning of role loop role_id=$role_id n_users_to_assign=$n_users_to_assign group_members=[array get group_members]"
962 962
963 963         set assignees [list]
964 964         for { set i 0 } { $i < $n_users_to_assign } { incr i } {
965 965             set user_was_cast_p 0
966 966
967 967             # Get the list of users in groups mapped to this role
968 968             set role_group_users [list]
969 969             foreach group_id [util::randomize_list $one_role(parties)] {
970 970                 set role_group_users [concat $role_group_users $group_members($group_id)]
971 971             }
972 972
973 973             # 1. Get random user from users_to_cast list who fulfils either of:
974 974             # a) User is in non-multiple case group mapped to role (group_members)
975 975             # b) User is in multi case group mapped to role (group_members)
976 976             # c) User is not in any group (users_to_cast_not_in_groups)          
  977             #ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - before users_to_cast loop, users_to_cast=$users_to_cast role_group_users=$role_group_users"
977 978             foreach user_id $users_to_cast {
978 979                
979 980                 set cast_user_p 0
980 981                 if { [lsearch $role_group_users $user_id] != -1 } {
981 982                     # Case a) or b) - user is in a group mapped to the role
982 983                     #ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - in users to assign loop, role_id=$role_id i=$i casting user_id=$user_id from group (case a or b)"
983 984
984 985                     set cast_user_p 1
985 986
986 987                     remove_user_from_casting_groups \
987 988                         -user_id $user_id \
988 989                         -role_groups $one_role(parties) \
989 990                         -groups_array group_members \
990 991                         -full_groups_array full_group_members \
991 992                         -multiple_case_groups $multiple_case_groups
  993                     #ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - in users_to_cast loop, after remove_users_from_casting_groups, group_members=[array get group_members]"
992 994
993 995                 } elseif { [lsearch $users_to_cast_not_in_groups $user_id] != -1 } {
994 996                     # Case c) - user not in a group mapped to any role
995 997                     #ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - in users to assign loop, role_id=$role_id i=$i casting user_id=$user_id who is not in group (case c)"
996 998
997 999                     set cast_user_p 1
998 1000
999 1001                     # Remove user from the users_to_cast_not_in_groups list
1000 1002                     set cast_list_index [lsearch -exact $users_to_cast_not_in_groups $user_id]
1001 1003                     set users_to_cast_not_in_groups [lreplace $users_to_cast_not_in_groups $cast_list_index $cast_list_index]
1002 1004                 }
1003 1005
1004 1006                 if { $cast_user_p } {
1005 1007                     # Cast user
1006 1008                     lappend assignees $user_id
1007 1009                     set user_was_cast_p 1
1008 1010
1009 1011                     # Remove user from users_to_cast list
1010 1012                     set cast_list_index [lsearch -exact $users_to_cast $user_id]
1011 1013                     set users_to_cast [lreplace $users_to_cast $cast_list_index $cast_list_index]
1012 1014
1013 1015                     break
1014 1016                 }
1015 1017             }
1016 1018
1017 1019             # 2. Get user from multiple group mapped to role (a user who is not in the users_to_cast list because he has been cast before)
1018 1020             if { !$user_was_cast_p } {
1019 1021                 foreach group_id $one_role(parties) {
1020                       if { [lsearch $multiple_case_groups $group_id] == -1 } {
  1022                     if { [lsearch $multiple_case_groups $group_id] != -1 } {
1021 1023                         # We have a non-empty (they are refilled) multiple group mapped to the role
1022 1024                         # Cast random user from that group
  1025                         set user_id [lindex $group_members($group_id) 0]
  1026
1023 1027                         #ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - in users to assign loop, role_id=$role_id i=$i casting already cast user_id=$user_id from multi case group $group_id"
1024 1028        
1025 1029                         set user_was_cast_p 1
1026 1030                         lappend assignees $user_id
1027 1031                        
1028 1032                         remove_user_from_casting_groups \
1029 1033                             -user_id $user_id \
1030 1034                             -role_groups $one_role(parties) \
1031 1035                             -groups_array group_members \
1032 1036                             -full_groups_array full_group_members \
1033 1037                             -multiple_case_groups $multiple_case_groups
1034 1038
1035 1039                         # Remove user from users_to_cast list
1036 1040                         set cast_list_index [lsearch -exact $users_to_cast $user_id]
1037 1041                         set users_to_cast [lreplace $users_to_cast $cast_list_index $cast_list_index]                       
1038 1042
1039 1043                         break
1040 1044                     }
1041 1045                 }
1042 1046             }
1043 1047
1044 1048             # 3. Last resort - cast admin (filler)
1045 1049             if { !$user_was_cast_p } {
1046 1050                 #ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - in users to assign loop, role_id=$role_id i=$i casting resorting to cast admin_user_id=$admin_user_id"
1047 1051                 set user_was_cast_p 1
1048 1052                 lappend assignees $admin_user_id
  1053                 # Only cast admin once
  1054                 break
1049 1055             }       
1050 1056         }
1051 1057
1052 1058         # Keep track of which users we decided to assign to the role and move on to the next one
1053           set row($role_short_name($role_id)) $assignees   
  1059         # It can happen with multi groups that a user gets mapped multiple times to one role. However, there is
  1060         # a role-party unique constraint in workflow that we mustn't violate.
  1061         # TODO: If we are removing a user here it means we are one of more users short
  1062         # of the targeted number of users for the role. In that case we should assign the admin as well if we haven't already done so.
  1063         set row($role_short_name($role_id)) [template::util::spellcheck::get_sorted_list_with_unique_elements -the_list $assignees]
1054 1064     }
1055 1065
1056 1066     # Do all the user-role assignments in the case
1057 1067     workflow::case::role::assign \
1058 1068         -case_id $case_id \
1059 1069         -array row \
1060 1070 }
1061 1071
1062 1072 ad_proc -private simulation::template::remove_user_from_casting_groups {
1063 1073     {-user_id:required}
1064 1074     {-role_groups:required}
1065 1075     {-groups_array:required}
1066 1076     {-full_groups_array:required}
1067 1077     {-multiple_case_groups:required}
1068 1078 } {
1069 1079     Remove a cast user from the groups data structure and refill and empty
1070 1080     multicase groups. This is an internal proc used by the casting algorithm.
1071 1081    
1072 1082     @author Peter Marklund
1073 1083 } {
1074 1084     upvar $groups_array group_members
1075 1085     upvar $full_groups_array full_group_members
1076 1086
1077 1087     # Remove the user from group_members
1078 1088     foreach group_id $role_groups {
1079 1089         set group_index [lsearch -exact $group_members($group_id) $user_id]
1080 1090         set group_members($group_id) [lreplace $group_members($group_id) $group_index $group_index]
1081 1091        
1082 1092         # Refill the group if it's now empty and multi-case
1083           if { [llength $group_members($group_id)] == 0 && [lsearch $multiple_case_groups $group_id] == -1 } {
  1093         if { [llength $group_members($group_id)] == 0 && [lsearch $multiple_case_groups $group_id] != -1 } {
1084 1094             set group_members($group_id) $full_group_members($group_id)           
1085 1095         }
1086 1096     }
1087 1097 }
1088 1098
1089 1099 ad_proc -private simulation::template::admin_user_id {
1090 1100     {-workflow_id:required}
1091 1101 } {
1092 1102     When starting a simulation, get the user if of the simulation admin. The simulation
1093 1103     admin is the creator of the simulation.
1094 1104
1095 1105     @author Peter Marklund
1096 1106 } {
1097 1107     return [db_string select_creation_user {
1098 1108         select creation_user
1099 1109         from acs_objects
1100 1110         where object_id = :workflow_id
1101 1111     }]
1102 1112 }
1103 1113