Skip to content

Commit 14a6df7

Browse files
authored
Enabled instructors to assign inactive students to groups (#7757)
1 parent 6cb94da commit 14a6df7

File tree

9 files changed

+94
-13
lines changed

9 files changed

+94
-13
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
### ✨ New features and improvements
88
- Enable test results downloads through the API (#7754)
99
- Provide suggestions for partial student matching scans (#7760)
10+
- Allow inactive students to join groups (#7757)
1011

1112
### 🐛 Bug fixes
1213

app/controllers/groups_controller.rb

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ def upload
306306

307307
group_rows << row.compact_blank
308308
end
309+
309310
if result[:invalid_lines].empty?
310311
@current_job = CreateGroupsJob.perform_later assignment, group_rows
311312
session[:job_id] = @current_job.job_id
@@ -489,8 +490,8 @@ def invite_member
489490
if errors.blank?
490491
to_invite.each do |i|
491492
i = i.strip
492-
invited_user = current_course.students.joins(:user).where(hidden: false).find_by('users.user_name': i)
493-
if invited_user.receives_invite_emails?
493+
invited_user = current_course.students.joins(:user).find_by('users.user_name': i)
494+
if invited_user&.receives_invite_emails?
494495
NotificationMailer.with(inviter: current_role,
495496
invited: invited_user,
496497
grouping: @grouping).grouping_invite_email.deliver_later
@@ -699,9 +700,6 @@ def add_member(student, grouping, assignment)
699700
end
700701
@bad_user_names = []
701702

702-
if student.hidden
703-
raise I18n.t('groups.invite_member.errors.not_found', user_name: student.user_name)
704-
end
705703
if student.has_accepted_grouping_for?(assignment.id)
706704
raise I18n.t('groups.invite_member.errors.already_grouped', user_name: student.user_name)
707705
end

app/models/grouping.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ def invite(members,
288288
all_errors = []
289289
members.each do |m|
290290
m = m.strip
291-
user = course.students.joins(:user).where(hidden: false).find_by('users.user_name': m)
291+
user = course.students.joins(:user).find_by('users.user_name': m)
292292
begin
293293
if user.nil?
294294
raise I18n.t('groups.invite_member.errors.not_found', user_name: m)
@@ -305,7 +305,7 @@ def invite(members,
305305

306306
# Add a new member to base
307307
def add_member(role, set_membership_status = StudentMembership::STATUSES[:accepted])
308-
if role.has_accepted_grouping_for?(self.assessment_id) || role.hidden
308+
if role.has_accepted_grouping_for?(self.assessment_id)
309309
nil
310310
else
311311
member = StudentMembership.new(role: role, membership_status:
@@ -329,6 +329,8 @@ def add_member(role, set_membership_status = StudentMembership::STATUSES[:accept
329329
def can_invite?(role)
330330
if self.inviter == role
331331
raise I18n.t('groups.invite_member.errors.inviting_self')
332+
elsif role.hidden
333+
raise I18n.t('groups.invite_member.errors.inactive_student', user_name: role.user_name)
332334
elsif !extension.nil?
333335
raise I18n.t('groups.invite_member.errors.extension_exists')
334336
elsif self.student_membership_number >= self.assignment.group_max

config/locales/views/groups/en.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ en:
4242
extension_exists: You cannot modify a group with an extension to the due date. Please contact your instructor if you wish to make changes.
4343
group_max_reached: 'Could not invite %{user_name}: group maximum has been reached.'
4444
inactive_grader: Cannot assign inactive grader(s) %{user_names}.
45+
inactive_student: 'Could not invite %{user_name}: this student is inactive.'
4546
inviting_self: You cannot invite yourself to your own group.
4647
need_to_create_group: You must create a group before you can invite members.
4748
not_found: No student '%{user_name}' could be found.

spec/controllers/groups_controller_spec.rb

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,8 @@
532532
# Setup for Git Repository
533533
allow(Settings.repository).to receive(:type).and_return('git')
534534

535-
@assignment = create(:assignment)
535+
# Create assignment with group_max of 3 to accommodate test files
536+
@assignment = create(:assignment, assignment_properties_attributes: { group_max: 3 })
536537

537538
# Create students corresponding to the file_good
538539
@student_user_names = %w[c8shosta c5bennet]
@@ -570,6 +571,67 @@
570571
expect(flash[:error]).not_to be_blank
571572
expect(response).to redirect_to(action: 'index')
572573
end
574+
575+
it 'accepts groups within the maximum group size' do
576+
@assignment.update!(assignment_properties_attributes: { group_max: 2 })
577+
# Students c8shosta and c5bennet are already created in the outer before block
578+
expect do
579+
post_as instructor, :upload, params: {
580+
course_id: course.id,
581+
assignment_id: @assignment.id,
582+
upload_file: fixture_file_upload('groups/form_good.csv', 'text/csv')
583+
}
584+
end.to have_enqueued_job(CreateGroupsJob)
585+
586+
expect(response).to have_http_status(:found)
587+
expect(flash[:error]).to be_blank
588+
expect(response).to redirect_to(action: 'index')
589+
end
590+
591+
it 'accepts single-member groups' do
592+
@assignment.update!(assignment_properties_attributes: { group_max: 1 })
593+
create(:student, user: create(:end_user, user_name: 'solo_student'))
594+
595+
csv_content = "group1,solo_student\n"
596+
file = Tempfile.new(['test_upload', '.csv'])
597+
file.write(csv_content)
598+
file.rewind
599+
600+
expect do
601+
post_as instructor, :upload, params: { course_id: course.id,
602+
assignment_id: @assignment.id,
603+
upload_file: fixture_file_upload(file.path, 'text/csv') }
604+
end.to have_enqueued_job(CreateGroupsJob)
605+
606+
file.close
607+
file.unlink
608+
609+
expect(flash[:error]).to be_blank
610+
end
611+
612+
context 'when uploading groups with inactive students' do
613+
before do
614+
@assignment.update!(assignment_properties_attributes: { group_max: 2 })
615+
# Create an active student
616+
@active_student = create(:student, user: create(:end_user, user_name: 'active_student'))
617+
# Create an inactive student (hidden: true)
618+
@inactive_student = create(:student, hidden: true, user: create(:end_user, user_name: 'inactive_student'))
619+
end
620+
621+
it 'allows importing groups with inactive students (ISSUE-7743)' do
622+
expect do
623+
post_as instructor, :upload, params: {
624+
course_id: course.id,
625+
assignment_id: @assignment.id,
626+
upload_file: fixture_file_upload('groups/form_with_inactive_students.csv', 'text/csv')
627+
}
628+
end.to have_enqueued_job(CreateGroupsJob)
629+
630+
expect(response).to have_http_status(:found)
631+
expect(flash[:error]).to be_blank
632+
expect(response).to redirect_to(action: 'index')
633+
end
634+
end
573635
end
574636

575637
describe '#create_groups_when_students_work_alone' do
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
group1,student1,student2,student3
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
group1,student1,student2,student3
2+
group2,student4,student5
3+
group3,student6,student7,student8
4+
group4,student9,student10,student11
5+
group5,student12,student13,student14
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
group1,active_student,inactive_student

spec/models/grouping_spec.rb

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,25 @@
4545
context 'hidden students' do
4646
let(:hidden) { create(:student, hidden: true) }
4747

48-
it 'cannot be invited' do
49-
grouping.invite(hidden.user.user_name)
50-
expect(grouping.memberships.count).to eq(0)
48+
it 'can be invited by instructors' do
49+
grouping.invite(hidden.user.user_name, StudentMembership::STATUSES[:accepted], invoked_by_instructor: true)
50+
expect(grouping.memberships.count).to eq(1)
51+
expect(grouping.memberships.first.role).to eq(hidden)
5152
end
5253

53-
it 'cannot be added' do
54-
grouping.add_member(hidden)
54+
it 'cannot be invited by students' do
55+
errors = grouping.invite(hidden.user.user_name)
56+
expect(errors).not_to be_empty
57+
expect(errors.first).to include('inactive')
5558
expect(grouping.memberships.count).to eq(0)
5659
end
60+
61+
it 'can be added' do
62+
result = grouping.add_member(hidden)
63+
expect(result).not_to be_nil
64+
expect(grouping.memberships.count).to eq(1)
65+
expect(grouping.memberships.first.role).to eq(hidden)
66+
end
5767
end
5868

5969
it 'displays Empty Group since no students in the group' do

0 commit comments

Comments
 (0)