Source code for uw.local.teaching.bin.send_final_examination_reminder

"""Termly final examination setup reminder sending process.

Implements the process to send email reminders to course staff to check that
their final examination is set up correctly.
"""

from uw.sql.wrap import open_psycopg2_db_service_cursor

from ...outgoing.make_mail import mailout
from ...util.mail import odyssey_email

from ..db.exam_print import message_to_course_staff

seating_text = {
    False: 'This examination is currently planned to have non-assigned seating, meaning students may sit anywhere within the designated rooms and/or PAC areas.',
    True: 'This examination is currently planned to have assigned seating, meaning students will be assigned a specific seat within the designated rooms and/or PAC areas.'
}

crowdmark_text = {
    False: 'This examination will not use Crowdmark.  No QR codes will be printed on the pages and no scanning will take place.',
    True: 'This examination will use Crowdmark.  QR codes will be printed in the upper corner of every page of the Answers booklet, and an assessment will be automatically created in Crowdmark when the examination is printed.  You must ensure that post-exam drop-off for W Print and marking dates are entered into Odyssey at least two weeks ahead of the examination date, but no later than the end of classes.  More information is available at https://uwaterloo.ca/crowdmark/midterms-and-final-exams.  Please contact cmadmin@uwaterloo.ca for questions regarding set up of Crowdmark exams.',
}

[docs]def notify_staff (cursor, term, exam): content_lines = [ 'You are receiving this email because you are recorded as being responsible for the %s being held %s.' % (exam.full_title, exam.times_formatted), '', seating_text[exam.exam_assigned], '', crowdmark_text[exam.is_crowdmark], '', 'If this is not what you want, please log in to the URL below and use the “Edit Seating” or “Edit Scanning” links as appropriate before Noon %s at the latest.' % term.check_deadline_date.strftime ('%A, %B %d'), '', ] if exam.ro_admin: content_lines.extend ([ 'The examination master submission deadline is %s.' % exam.deadline_date.strftime ('%A, %Y-%m-%d'), '', 'Please upload and approve the master PDF on or before this date in order to qualify for the Registrar’s Office to fund the printing and deliver the printed papers to the examination venue.', 'If you miss the deadline, you may still upload and approve the master PDF, but the department will have to pay for printing and the papers will be delivered to your department.', ]) content_lines.extend ([ 'You may need to log in to the URL below and fill in the “Authorized Uploader” before the “Upload Masters” link will appear for you.', '', 'https://odyssey.uwaterloo.ca/teaching/term/%s/%s/exam/%s/' % (exam.term_id, exam.admin_id, exam.exam_id), ]) content = '\n'.join (content_lines) message = mailout (cursor, odyssey_email, 'Assessment Printing for %s on %s' % (exam.full_title, exam.primary_start_time.strftime ('%A, %Y-%m-%d')), content) message_to_course_staff (cursor, message, exam.term_id, exam.admin_id, ['ISC']) message.add_recipient ('Cc', odyssey_email) message.done ()
[docs]def main (): cursor = open_psycopg2_db_service_cursor () term = cursor.execute_required_tuple ("select distinct on (term_id) term_id, deadline_date as check_deadline_date from uw_term natural join exam_print_deadline where (term_id, administer_admin_id) = (uw_term_current (), 20050) order by term_id, period_id") for exam in cursor.execute_tuples ("select exam_id, admin_id, term_id, exam_assigned, not eec is null as is_crowdmark, exam_exam_full_title (exam_id) as full_title, primary_start_time, exam_time_format_times (primary_start_time, exam_duration) as times_formatted, administer_admin_id is not distinct from 20050 as ro_admin, deadline_date from exam_exam_print_deadline left join exam_exam_crowdmark eec using (exam_id) natural join teaching_admin_term where term_id = %(term_id)s and series_code in ('F', 'LF') and admin_assigned is not null and administer_admin_id is distinct from 20070 order by primary_start_time nulls first, full_title", term_id=term.term_id): if exam.primary_start_time is None: print ('skipping %s because no primary start time set' % exam.full_title) continue notify_staff (cursor, term, exam) cursor.connection.commit ()