def test_scheduled_filter(self, client, admin_session): """Scheduled filter: Courses with recordings scheduled.""" with test_approvals_workflow(app): # Send invites for section_id in [section_1_id, section_6_id]: self._send_invitation_email(section_id) self._create_approval(section_id) # Feed will only include courses that were scheduled. mock_scheduled( section_id=section_1_id, term_id=self.term_id, ) # Deleted records will be ignored mock_scheduled( section_id=section_2_id, term_id=self.term_id, ) Scheduled.delete(section_id=section_2_id, term_id=self.term_id) std_commit(allow_test_environment=True) api_json = self._api_courses(client, term_id=self.term_id, filter_='Scheduled') assert len(api_json) == 1 course = _find_course(api_json=api_json, section_id=section_1_id) assert course['approvalStatus'] == 'Partially Approved' assert course['schedulingStatus'] == 'Scheduled' assert not _find_course(api_json=api_json, section_id=section_6_id)
def unschedule(): params = request.get_json() term_id = params.get('termId') section_id = params.get('sectionId') course = SisSection.get_course(term_id, section_id, include_deleted=True) if (term_id and section_id) else None if not course: raise BadRequestError('Required params missing or invalid') if not (course['scheduled'] or course['hasNecessaryApprovals']): raise BadRequestError(f'Section id {section_id}, term id {term_id} is not currently scheduled or queued for scheduling') Approval.delete(term_id=term_id, section_id=section_id) Scheduled.delete(term_id=term_id, section_id=section_id) event_id = (course.get('scheduled') or {}).get('kalturaScheduleId') if event_id: try: Kaltura().delete(event_id) except (KalturaClientException, KalturaException) as e: message = f'Failed to delete Kaltura schedule: {event_id}' app.logger.error(message) app.logger.exception(e) send_system_error_email( message=f'{message}\n\n<pre>{traceback.format_exc()}</pre>', subject=message, ) CoursePreference.update_opt_out( term_id=term_id, section_id=section_id, opt_out=True, ) return tolerant_jsonify(SisSection.get_course(term_id, section_id, include_deleted=True))
def test_room_change_no_longer_eligible(self, db_session): section_id = 50004 term_id = app.config['CURRENT_TERM_ID'] def _move_course(meeting_location): db.session.execute( text( 'UPDATE sis_sections SET meeting_location = :meeting_location WHERE term_id = :term_id AND section_id = :section_id' ), { 'meeting_location': meeting_location, 'section_id': section_id, 'term_id': term_id, }, ) with enabled_job(job_key=InstructorEmailsJob.key()): with test_approvals_workflow(app): course = SisSection.get_course(section_id=section_id, term_id=term_id) eligible_meetings = course.get('meetings', {}).get('eligible', []) assert len(eligible_meetings) == 1 original_room = eligible_meetings[0]['room'] assert original_room['location'] == 'Li Ka Shing 145' # Schedule _schedule(original_room['id'], section_id) _run_instructor_emails_job() _assert_email_count(0, section_id, 'room_change_no_longer_eligible') # Move course to some other eligible room. _move_course('Barker 101') _run_instructor_emails_job() _assert_email_count(0, section_id, 'room_change_no_longer_eligible') # Move course to an ineligible room. ineligible_room = 'Wheeler 150' _move_course(ineligible_room) _run_instructor_emails_job() _assert_email_count(1, section_id, 'room_change_no_longer_eligible') # Move course back to its original location _move_course(original_room['location']) # Finally, let's pretend the course is scheduled to a room that was previously eligible. Scheduled.delete(section_id=section_id, term_id=term_id) _schedule(Room.find_room(ineligible_room).id, section_id) _run_instructor_emails_job() # Expect email. _assert_email_count(2, section_id, 'room_change_no_longer_eligible') Scheduled.delete(section_id=section_id, term_id=term_id)
def test_admin_alert_date_change(self, db_session): with enabled_job(job_key=AdminEmailsJob.key()): admin_uid = app.config['EMAIL_DIABLO_ADMIN_UID'] term_id = app.config['CURRENT_TERM_ID'] section_id = 50004 meeting = get_eligible_meeting(section_id=section_id, term_id=term_id) with test_approvals_workflow(app): with override_config(app, 'CURRENT_TERM_RECORDINGS_BEGIN', meeting['startDate']): with override_config(app, 'CURRENT_TERM_RECORDINGS_END', meeting['endDate']): def _run_jobs(): AdminEmailsJob(simply_yield).run() QueuedEmailsJob(simply_yield).run() def _schedule(): mock_scheduled( meeting=meeting, override_end_time='16:59', override_start_time='08:00', section_id=section_id, term_id=term_id, ) course = SisSection.get_course( section_id=section_id, term_id=term_id) scheduled = course['scheduled'] assert are_scheduled_dates_obsolete( meeting=meeting, scheduled=scheduled) is False assert are_scheduled_times_obsolete( meeting=meeting, scheduled=scheduled) is True def _assert_alert_count(count): emails_sent = SentEmail.get_emails_sent_to( uid=admin_uid) assert len(emails_sent) == count assert emails_sent[0].section_id == section_id assert emails_sent[ 0].template_type == 'admin_alert_date_change' # First time scheduled. _schedule() _run_jobs() _assert_alert_count(1) # Unschedule and schedule a second time. Scheduled.delete(section_id=section_id, term_id=term_id) _schedule() _run_jobs() # Another alert is emailed to admin because it is a new schedule. _assert_alert_count(2) # Run jobs again and expect no alerts. _run_jobs() _assert_alert_count(2)
def test_partially_approved_filter(self, client, admin_session): """Partially approved: Eligible, invited course with 1+ approvals, but not ALL instructors have approved.""" with test_approvals_workflow(app): for section_id in [section_1_id, section_6_id, section_7_id]: # Assert multiple instructors assert len(get_instructor_uids(section_id=section_id, term_id=self.term_id)) > 1 # Send invites self._send_invitation_email(section_id) if section_id == section_1_id: # If course is "approved" by admin only then it will NOT show up on the partially-approval list. Approval.create( approved_by_uid=admin_uid, approver_type_='admin', publish_type_='kaltura_my_media', recording_type_='presentation_audio', room_id=Room.get_room_id(section_id=section_id, term_id=self.term_id), section_id=section_id, term_id=self.term_id, ) else: # Approval by first instructor only self._create_approval(section_id) # Feed will include both scheduled and not scheduled. for section_id in [section_1_id, section_7_id]: mock_scheduled(section_id=section_id, term_id=self.term_id) # Unschedule one of them Approval.delete(section_id=section_7_id, term_id=self.term_id) Scheduled.delete(section_id=section_7_id, term_id=self.term_id) std_commit(allow_test_environment=True) api_json = self._api_courses(client, term_id=self.term_id, filter_='Partially Approved') assert len(api_json) == 1 course = _find_course(api_json=api_json, section_id=section_6_id) assert course assert course['label'] == 'LAW 23, LEC 002' assert course['approvalStatus'] == 'Partially Approved' assert course['schedulingStatus'] == 'Not Scheduled'
def test_room_change_no_longer_eligible(self, db_session): with enabled_job(job_key=InstructorEmailsJob.key()): term_id = app.config['CURRENT_TERM_ID'] section_id = 50004 with test_approvals_workflow(app): def _run_jobs(): InstructorEmailsJob(simply_yield).run() QueuedEmailsJob(simply_yield).run() def _schedule(): mock_scheduled( override_room_id=Room.find_room('Barker 101').id, section_id=section_id, term_id=term_id, ) course = SisSection.get_course(section_id=section_id, term_id=term_id) assert course['scheduled']['hasObsoleteRoom'] is True def _assert_alert_count(count): emails_sent = SentEmail.get_emails_of_type( section_ids=[section_id], template_type='room_change_no_longer_eligible', term_id=term_id, ) assert len(emails_sent) == count # First time scheduled. _schedule() _run_jobs() _assert_alert_count(1) # Unschedule and schedule a second time. Scheduled.delete(section_id=section_id, term_id=term_id) _schedule() _run_jobs() # Another alert is emailed to admin because it is a new schedule. _assert_alert_count(2) # Run jobs again and expect no alerts. _run_jobs() _assert_alert_count(2)