def __init__(self, *args, **kwargs): flags = kwargs.pop('flags', []) super(CourseAccreditationForm, self).__init__(*args, **kwargs) if 'start_semester' not in self.data: self.data['start_semester'] = Semester.current().name if 'end_semester' not in self.data: self.data['end_semester'] = Semester.current().name self.fields['flag'].choices = flags
def run(self): AcceptedStudentsQuery = AcceptedQuery({'strm': Semester.current().offset_name(1), 'acad_plans': ['CMPTMAJ', 'DCMPT', 'CMPTMIN', 'CMPTHON', 'CMPTJMA', 'CMPTJHO', 'SOSYMAJ', 'ZUSFU']}) AcceptedStudents = AcceptedStudentsQuery.result() EnrolledStudentsQuery = EnrolledQuery({'strm': Semester.current().offset_name(1), 'acad_progs': ['CMPT', 'CMPT2']}) EnrolledStudents = EnrolledStudentsQuery.result() # Let's calculate our totals so we can display those numbers as well. accepted_list = AcceptedStudents.column_as_list("SEX") accepted_total = len(accepted_list) accepted_m_count = len([i for i in accepted_list if i=='M']) accepted_f_count = len([i for i in accepted_list if i=='F']) accepted_u_count = len([i for i in accepted_list if i=='U']) enrolled_list = EnrolledStudents.column_as_list("SEX") enrolled_total = len(enrolled_list) enrolled_m_count = len([i for i in enrolled_list if i == 'M']) enrolled_f_count = len([i for i in enrolled_list if i == 'F']) enrolled_u_count = len([i for i in enrolled_list if i == 'U']) # Let's create two new tables to display these results. accepted_totals = Table() accepted_totals.append_column('TOTAL_COUNT') accepted_totals.append_column('M_COUNT') accepted_totals.append_column('M_PERCENT') accepted_totals.append_column('F_TOTAL') accepted_totals.append_column('F_PERCENT') accepted_totals.append_column('U_COUNT') accepted_totals.append_column('U_PERCENT') accepted_totals.append_row([accepted_total, accepted_m_count, 100.0 * accepted_m_count/accepted_total, accepted_f_count, 100.0 * accepted_f_count/accepted_total, accepted_u_count, 100.0 * accepted_u_count/accepted_total]) enrolled_totals = Table() enrolled_totals.append_column('TOTAL_COUNT') enrolled_totals.append_column('M_COUNT') enrolled_totals.append_column('M_PERCENT') enrolled_totals.append_column('F_TOTAL') enrolled_totals.append_column('F_PERCENT') enrolled_totals.append_column('U_COUNT') enrolled_totals.append_column('U_PERCENT') enrolled_totals.append_row([enrolled_total, enrolled_m_count, 100.0 * enrolled_m_count / enrolled_total, enrolled_f_count, 100.0 * enrolled_f_count / enrolled_total, enrolled_u_count, 100.0 * enrolled_u_count / enrolled_total]) self.artifacts.append(AcceptedStudents) self.artifacts.append(accepted_totals) self.artifacts.append(EnrolledStudents) self.artifacts.append(enrolled_totals)
def run(self): current_semester = Semester.current() semesters = [current_semester.name, current_semester.offset_name(-1), current_semester.offset_name(-2)] cmpt_acad_progs, eng_acad_progs = get_fas_programs() cmpt_gpas = self.bad_gpa_for(cmpt_acad_progs, semesters, '2.4') eng_gpas = self.bad_gpa_for(eng_acad_progs, semesters, '2.5') bad_gpas = cmpt_gpas for r in (eng_gpas.rows): bad_gpas.append_row(r) name_query = NameQuery() names = name_query.result() email_query = EmailQuery() email = email_query.result() email.filter( EmailQuery.preferred_email ) bad_gpas.left_join( names, "EMPLID" ) bad_gpas.left_join( email, "EMPLID" ) bad_gpas.remove_column('E_ADDR_TYPE') bad_gpas.remove_column('PREF_EMAIL_FLAG') self.artifacts.append(bad_gpas)
def run(self): cmpt_progs, eng_progs = get_fas_programs() fas_progs = cmpt_progs + eng_progs # collect student data for every semester in the last year. # Do it here because I'm not smart enough to do it in SQL. semester = Semester.current() last_yr = [semester.offset_name(-2), semester.offset_name(-1), semester.name] student_data = {} for strm in last_yr: students = InternationalGPAQuery({ 'acad_progs': fas_progs, 'strm': strm, }).result() for r in students.rows: emplid = r[0] student_data[emplid] = r students.rows = student_data.values() visits = AdvisorVisits(unit_slugs=['apsc']).result() notes = AdvisorNotes(unit_slugs=['apsc']).result() students.left_join(visits, 'EMPLID') students.left_join(notes, 'EMPLID') self.artifacts.append(students)
def create_reminder_messages(self, start_date=None, end_date=None, allow_stale=True): """ Create any ReminderMessages that don't already exist, between startdate and enddate. Idempotent. """ if self.status == 'D': return if not start_date or not end_date: start_date, end_date = self.reminder_message_range(allow_stale=allow_stale) if self.date_type == 'YEAR': next1 = datetime.date(year=start_date.year, month=int(self.month), day=self.day) next2 = datetime.date(year=start_date.year+1, month=int(self.month), day=self.day) self.create_reminder_on(next1, start_date, end_date) self.create_reminder_on(next2, start_date, end_date) elif self.date_type == 'SEM': if self.reminder_type == 'INST': # limit to semesters actually teaching instructors = Member.objects.filter(role='INST', person=self.person, offering__course=self.course) \ .exclude(offering__component='CAN').select_related('offering__course') semesters = {m.offering.semester for m in instructors} else: semesters = None this_sem = Semester.current() for sem in [this_sem.previous_semester(), this_sem, this_sem.next_semester()]: if semesters is None or sem in semesters: next = sem.duedate(self.week, int(self.weekday), time=None) self.create_reminder_on(next, start_date, end_date) else: raise ValueError()
def run(self): current_semester = Semester.current() semesters = [current_semester.name, current_semester.offset_name(-1), current_semester.offset_name(-2)] cmpt_acad_progs = AcadProgsOwnedByUnit({'acad_org': 'COMP SCI'}) \ .result() \ .column_as_list('ACAD_PROG') eng_acad_progs = DegreeAcadProgs() \ .result() \ .column_as_list('ACAD_PROG') cmpt_gpas = self.bad_gpa_for(cmpt_acad_progs, semesters, '2.4') eng_gpas = self.bad_gpa_for(eng_acad_progs, semesters, '2.5') bad_gpas = cmpt_gpas for r in (eng_gpas.rows): bad_gpas.append_row(r) name_query = NameQuery() names = name_query.result() email_query = EmailQuery() email = email_query.result() email.filter( EmailQuery.preferred_email ) bad_gpas.left_join( names, "EMPLID" ) bad_gpas.left_join( email, "EMPLID" ) bad_gpas.remove_column('E_ADDR_TYPE') bad_gpas.remove_column('PREF_EMAIL_FLAG') self.artifacts.append(bad_gpas)
def make_entry_field(self, fieldsubmission=None): queryset = Semester.objects.all().order_by('name') allowed = self.config.get('allowed_semesters', 'AL') current = Semester.current().name if allowed == 'AL': pass elif allowed == 'LT': queryset = queryset.filter(name__lt=current).order_by('-name') elif allowed == 'LE': queryset = queryset.filter(name__lte=current).order_by('-name') elif allowed == 'GT': queryset = queryset.filter(name__gt=current) elif allowed == 'GE': queryset = queryset.filter(name__gte=current) the_choices = [(s.name, s.label()) for s in queryset] widget = forms.Select if self.config.get('format', 'D') == 'R': widget = forms.RadioSelect c = forms.ChoiceField(required=self.config['required'], label=self.config['label'], help_text=self.config['help_text'], choices=the_choices, widget=widget,) if fieldsubmission: c.initial = fieldsubmission.data['info'] if not self.config['required']: c.choices.insert(0, ('', u'\u2014')) return c
def manage_program(request, grad_slug): grad = get_object_or_404(GradStudent, slug=grad_slug, program__unit__in=request.units) programs = GradProgram.objects.filter(unit__in=request.units) # If you have access to programs from different units, display them. if len(request.units) > 1: program_choices = [(p.id, str(p) + " (" + p.unit.label + ")") for p in programs] else: program_choices = [(p.id, str(p)) for p in programs] programhistory = GradProgramHistory.objects.filter(student=grad, program__unit__in=request.units).order_by('starting') if request.method == 'POST': form = GradProgramHistoryForm(request.POST) form.fields['program'].choices = program_choices if form.is_valid(): gph = form.save(commit=False) gph.student = grad gph.save() grad.update_status_fields() messages.success(request, "Updated program info for %s." % (grad.person)) l = LogEntry(userid=request.user.username, description="Updated grad program for %s." % (grad), related_object=gph) l.save() return HttpResponseRedirect(reverse('grad:view', kwargs={'grad_slug':grad.slug})) else: form = GradProgramHistoryForm(initial={'program': grad.program, 'semester': Semester.current()}) form.fields['program'].choices = program_choices context = { 'form': form, 'grad': grad, 'programhistory': programhistory, } return render(request, 'grad/manage_program.html', context)
def course_home_pages(request): semester = Semester.current() units = Unit.objects.all().order_by('label') units = [u for u in units if _has_homepages(u.id, semester.id)] context = { 'semester': semester, 'units': units, } return render(request, "coredata/course_home_pages.html", context)
def create_grads(): """ Put the grad students created before into GradStudent records. """ gp = GradProgram(unit=Unit.objects.get(slug='cmpt'), label='MSc Project', description='MSc Project option') gp.save() req = GradRequirement(program=gp, description='Formed Committee') req.save() gp = GradProgram(unit=Unit.objects.get(slug='cmpt'), label='MSc Thesis', description='MSc Thesis option') gp.save() req = GradRequirement(program=gp, description='Formed Committee') req.save() gp = GradProgram(unit=Unit.objects.get(slug='cmpt'), label='PhD', description='PhD') gp.save() req = GradRequirement(program=gp, description='Defended Thesis') req.save() req = GradRequirement(program=gp, description='Formed Committee') req.save() gp = GradProgram(unit=Unit.objects.get(slug='ensc'), label='MEng', description='Masters in Engineering') gp.save() gp = GradProgram(unit=Unit.objects.get(slug='ensc'), label='PhD', description='PhD') gp.save() st = ScholarshipType(unit=Unit.objects.get(slug='cmpt'), name="Some Scholarship") st.save() gf = GradFlag(unit=Unit.objects.get(slug='cmpt'), label='Special Specialist Program') gf.save() programs = list(GradProgram.objects.all()) supervisors = list(set([m.person for m in Member.objects.filter(offering__owner__slug='cmpt', role='INST')])) for p in Person.objects.filter(userid__endswith='grad'): gp = random.choice(programs) campus = random.choice(list(CAMPUSES)) gs = GradStudent(person=p, program=gp, campus=campus) gs.save() startsem = random.choice(list(Semester.objects.filter(name__lt=Semester.current().name))) st = GradStatus(student=gs, status='COMP', start=startsem) st.save() st = GradStatus(student=gs, status=random.choice(['ACTI', 'ACTI', 'LEAV']), start=startsem.next_semester()) st.save() if random.random() > 0.5: st = GradStatus(student=gs, status=random.choice(['GRAD', 'GRAD', 'WIDR']), start=startsem.next_semester().next_semester().next_semester()) st.save() if random.random() > 0.25: sup = Supervisor(student=gs, supervisor=random.choice(supervisors), supervisor_type='SEN') sup.save() sup = Supervisor(student=gs, supervisor=random.choice(supervisors), supervisor_type='COM') sup.save() if random.random() > 0.5: sup = Supervisor(student=gs, supervisor=random.choice(supervisors), supervisor_type='COM') sup.save() else: sup = Supervisor(student=gs, external="Some External Supervisor", supervisor_type='COM', config={'email': '*****@*****.**'}) sup.save()
def progress_reports(request): last_semester = Semester.current().previous_semester() CS_UNIT=Unit.objects.get(label='CMPT') grads = GradStudent.objects.filter(program__unit=CS_UNIT, start_semester__name__lte=last_semester.name, #grads = GradStudent.objects.filter(program__unit__in=request.units, start_semester__name__lte=last_semester.name, end_semester=None, current_status__in=['ACTI', 'LEAV', 'PART']) \ .select_related('person', 'program__unit').order_by('person') #grads = grads[:50] query_text = generate_queries(['queried students starting in %s or before: %i students'%(last_semester.name, grads.count())], grads) query_text = ''.join(query_text) return HttpResponse(query_text, content_type='text/plain')
def update_grads(): """ Update any currently-relevant grad students """ active = GradStudent.objects.filter(current_status__in=STATUS_ACTIVE).select_related('person') applicants = GradStudent.objects.filter(current_status__in=STATUS_APPLICANT, updated_at__gt=datetime.datetime.now()-datetime.timedelta(days=7)).select_related('person') s = Semester.current().offset(1) far_applicants = GradStudent.objects.filter(start_semester__name__gte=s.name).select_related('person') for gs in set(itertools.chain(active, applicants, far_applicants)): get_person_grad(gs.person.emplid)
def list_all_semesters(request): semesters = HiringSemester.objects.visible(request.units) # if you have access to more than one unit, # you can see more than one unit display_units = False if len(request.units) > 1: display_units = True try: current_semester = Semester.current() except Semester.DoesNotExist: current_semester = None try: next_semester = Semester.current().offset(1) except Semester.DoesNotExist: next_semester = None # If the user has multiple request.units, it's possible that they may # have to deal with more than one HiringSemester per Semester if current_semester: current_hiring_semesters = HiringSemester.objects.semester\ (current_semester.name, request.units) else: current_hiring_semesters = [] if next_semester: next_hiring_semesters = HiringSemester.objects.semester\ (next_semester.name, request.units) else: next_hiring_semesters = [] return render(request, 'tacontracts/list_all_semesters.html', { 'display_units':display_units, 'semesters':semesters, 'current_semester': current_semester, 'current_hiring_semesters':current_hiring_semesters, 'next_semester': next_semester, 'next_hiring_semesters':next_hiring_semesters })
def make_entry_field(self, fieldsubmission=None): current = Semester.current() # always limit to 10 years on either side of today: that seems like a reasonable window queryset = Semester.objects \ .filter(name__gte=current.offset_name(-30), name__lte=current.offset_name(30)) \ .order_by('name') allowed = self.config.get('allowed_semesters', 'AL') if allowed == 'AL': initial = current.name elif allowed == 'LT': queryset = queryset.filter(name__lt=current.name).order_by('-name') initial = current.offset_name(-1) elif allowed == 'LE': queryset = queryset.filter(name__lte=current.name).order_by('-name') initial = current.name elif allowed == 'GT': queryset = queryset.filter(name__gt=current.name) initial = current.offset_name(1) elif allowed == 'GE': queryset = queryset.filter(name__gte=current.name) initial = current.name the_choices = [(s.name, s.label()) for s in queryset] widget = forms.Select if self.config.get('format', 'D') == 'R': widget = forms.RadioSelect required = self.config['required'] if not required: initial = None c = forms.ChoiceField(required=required, label=self.config['label'], help_text=self.config['help_text'], choices=the_choices, widget=widget, initial=initial) if fieldsubmission: c.initial = fieldsubmission.data['info'] if not self.config['required']: c.choices.insert(0, ('', '\u2014')) return c
def test_grad_status(self): client = Client() test_auth(client, 'ggbaker') this_sem = Semester.current() # clear the deck on this student's statuses gs = self.__make_test_grad() gs.gradstatus_set.all().delete() s1 = GradStatus(student=gs, status='COMP', start=this_sem.offset(-4)) s1.save() s2 = GradStatus(student=gs, status='ACTI', start=this_sem.offset(-3)) s2.save() s3 = GradStatus(student=gs, status='LEAV', start=this_sem.offset(2)) s3.save() gs = GradStudent.objects.get(id=gs.id) # make sure we get what's in the database now self.assertEqual(gs.current_status, 'ACTI') # check status in a particular semester results self.assertEqual(gs.status_as_of(this_sem.offset(-6)), None) self.assertEqual(gs.status_as_of(this_sem.offset(-4)), 'COMP') self.assertEqual(gs.status_as_of(this_sem.offset(-3)), 'ACTI') self.assertEqual(gs.status_as_of(this_sem), 'ACTI') self.assertEqual(gs.status_as_of(this_sem.offset(1)), 'ACTI') self.assertEqual(gs.status_as_of(this_sem.offset(2)), 'LEAV') self.assertEqual(gs.status_as_of(this_sem.offset(3)), 'LEAV') # grad.tasks.update_statuses_to_current will put this student on LEAV on the first day of that future semester # check that "active" statuses are preferred over "applicant" statuses in status calcs s4 = GradStatus(student=gs, status='COMP', start=this_sem.offset(-3)) s4.save() self.assertEqual(gs.status_as_of(this_sem.offset(-3)), 'ACTI') # because of insanity that makes strange sense, application-decision statuses propagate back a semester gs.gradstatus_set.all().delete() s1 = GradStatus(student=gs, status='COMP', start=this_sem) s1.save() s2 = GradStatus(student=gs, status='REJE', start=this_sem.offset(1)) s2.save() self.assertEqual(gs.status_as_of(this_sem.offset(-1)), 'COMP') self.assertEqual(gs.status_as_of(this_sem), 'REJE') self.assertEqual(gs.status_as_of(this_sem.offset(1)), 'REJE')
def update_statuses_to_current(): """ Update the denormalized grad status fields to reflect the current time (and catch statuses that were entered in the future). Doesn't really need to be run daily, but that's easier than catching the missed celery run on the first day of class. """ this_sem = Semester.current() # grads who have a status or program that starts this semester status_student_ids = GradStatus.objects.filter(start=this_sem).order_by().values_list('student_id', flat=True) program_student_ids = GradProgramHistory.objects.filter(start_semester=this_sem).order_by().values_list('student_id', flat=True) student_ids = set(status_student_ids) | set(program_student_ids) students = set(GradStudent.objects.filter(id__in=student_ids).distinct()) # make sure it is actually in the status fields for gs in students: gs.update_status_fields()
def new_teaching_equivalent_inst(request): """ Instructors form to create a new teaching equivalent """ instructor = get_object_or_404(Person, userid=request.user.username) if request.method == 'POST': form = TeachingEquivForm(request.POST) if form.is_valid(): equivalent = form.save(commit=False) equivalent.credits_numerator = form.cleaned_data['credits_numerator'] equivalent.credits_denominator = form.cleaned_data['credits_denominator'] equivalent.instructor = instructor equivalent.status = 'UNCO' equivalent.save() messages.add_message(request, messages.SUCCESS, "Teaching Equivalent successfully created") return HttpResponseRedirect(reverse('planning.views.view_teaching_credits_inst')) else: form = TeachingEquivForm(initial={'semester': Semester.current().next_semester()}) return render(request, 'planning/new_teaching_equiv_inst.html', {'form': form})
def test_staff_page(self): """ Check the requires_course_staff_by_slug decorator. """ # a URL and some members/non-members url = reverse('offering:class_list', kwargs={'course_slug': TEST_COURSE_SLUG}) instr = "ggbaker" ta = Member.objects.filter(offering__slug=TEST_COURSE_SLUG, role='TA')[0].person.userid student = "0aaa0" nobody = "0bbb6" client = Client() # try without logging in response = client.get(url) self.assertEqual(response.status_code, 302) # try as instructor client.login_user(instr) response = client.get(url) self.assertEqual(response.status_code, 200) validate_content(self, response.content, url) # try as TA. client.login_user(ta) response = client.get(url) self.assertEqual(response.status_code, 200) # try as student client.login_user(student) response = client.get(url) self.assertEqual(response.status_code, 403) # try as non-member client.login_user(nobody) response = client.get(url) self.assertEqual(response.status_code, 403) # try again as TA, but cheat by changing the semester for the course first. We also have to change something # else, in this case, the section, in order to avoid violating unique constraints when saving it. c = CourseOffering.objects.get(slug=TEST_COURSE_SLUG) c.semester = Semester.current() c.section = 'q100' c.save() client.login_user(ta) response = client.get(url) self.assertEqual(response.status_code, 200)
def __make_test_grad(self): gs = GradStudent.objects.get(person__userid=self.gs_userid) sem = Semester.current() # put some data there so there's something to see in the tests (also, the empty <tbody>s don't validate) req = GradRequirement(program=gs.program, description="Some Requirement") req.save() st = ScholarshipType(unit=gs.program.unit, name="Some Scholarship") st.save() Supervisor(student=gs, supervisor=Person.objects.get(userid='ggbaker'), supervisor_type='SEN').save() GradProgramHistory(student=gs, program=gs.program).save() GradStatus(student=gs, status='ACTI', start=sem).save() CompletedRequirement(student=gs, requirement=req, semester=sem).save() Scholarship(student=gs, scholarship_type=st, amount=1000, start_semester=sem, end_semester=sem).save() OtherFunding(student=gs, amount=100, semester=sem, description="Some Other Funding", comments="Other Funding\n\nComment").save() Promise(student=gs, amount=10000, start_semester=sem, end_semester=sem.next_semester()).save() FinancialComment(student=gs, semester=sem, comment_type='SCO', comment='Some comment.\nMore.', created_by='ggbaker').save() Supervisor(student=gs, supervisor=Person.objects.get(userid='ggbaker'), supervisor_type='SEN').save() return gs
def student_data(self): """ Give one lucky student some more data that we can work wtih. """ cmpt = Unit.objects.get(slug='cmpt') msc = GradProgram.objects.get(unit=cmpt, slug='mscthesis') phd = GradProgram.objects.get(unit=cmpt, slug='phd') gs = GradStudent.objects.get(person__userid='0xxxgrad', program__unit=cmpt) start = Semester.current().offset(-3) # create some program history ph = get_or_create_nosave(GradProgramHistory, student=gs, program=msc) ph.start_semester = start ph.save() ph = get_or_create_nosave(GradProgramHistory, student=gs, program=phd) ph.start_semester = start.offset(3) ph.save() # give him some money stype = ScholarshipType.objects.filter(unit=cmpt)[0] sch = get_or_create_nosave(Scholarship, student=gs, scholarship_type=stype) sch.amount = 2000 sch.start_semester = start sch.end_semester = start.offset(2) sch.save() of = get_or_create_nosave(OtherFunding, student=gs, semester=start.offset(3)) of.amount = 1300 of.description = "Money fell from the sky" of.save() # promise p = get_or_create_nosave(Promise, student=gs, start_semester=start) p.end_semester = start.offset(2) p.amount = 10000 p.save() p = get_or_create_nosave(Promise, student=gs, start_semester=start.offset(3)) p.end_semester = start.offset(5) p.amount = 10000 p.save()
def test_advanced_search_3(self): client = Client() test_auth(client, 'ggbaker') this_sem = Semester.current() units = [r.unit for r in Role.objects.filter(person__userid='ggbaker', role='GRAD')] gs = self.__make_test_grad() gs.gradstatus_set.all().delete() s1 = GradStatus(student=gs, status='COMP', start=this_sem.offset(-4)) s1.save() s2 = GradStatus(student=gs, status='ACTI', start=this_sem.offset(-3)) s2.save() s3 = GradStatus(student=gs, status='LEAV', start=this_sem.offset(2)) s3.save() # test current-status searching form = SearchForm(QueryDict('student_status=ACTI&columns=person.emplid')) active_now = form.search_results(units) self.assertIn(gs, active_now) form = SearchForm(QueryDict('student_status=LEAV&columns=person.emplid')) leave_now = form.search_results(units) self.assertNotIn(gs, leave_now) # test status-as-of searching form = SearchForm(QueryDict('student_status=ACTI&status_asof=%s&columns=person.emplid' % (this_sem.offset(-4).name))) active_past = form.search_results(units) self.assertNotIn(gs, active_past) form = SearchForm(QueryDict('student_status=COMP&status_asof=%s&columns=person.emplid' % (this_sem.offset(-4).name))) applic_past = form.search_results(units) #self.assertIn(gs, applic_past) form = SearchForm(QueryDict('student_status=ACTI&status_asof=%s&columns=person.emplid' % (this_sem.offset(3).name))) active_later = form.search_results(units) self.assertNotIn(gs, active_later) form = SearchForm(QueryDict('student_status=LEAV&status_asof=%s&columns=person.emplid' % (this_sem.offset(3).name))) leave_later = form.search_results(units) self.assertIn(gs, leave_later)
def course_home_pages_unit(request, unit_slug, semester=None): if semester: semester = get_object_or_404(Semester, name=semester) else: semester = Semester.current() unit = get_object_or_404(Unit, slug=unit_slug) offerings = CourseOffering.objects.filter(semester=semester, owner=unit, graded=True) \ .exclude(component='CAN') \ .exclude(instr_mode__in=['CO', 'GI']) if request.user.is_authenticated(): is_admin = Role.objects.filter(unit=unit, person__userid=request.user.username, role='ADMN').exists() else: is_admin = False context = { 'semester': semester, 'unit': unit, 'offerings': offerings, 'is_admin': is_admin, } return render(request, "coredata/course_home_pages_unit.html", context)
def manage_status(request, grad_slug): grad = get_object_or_404(GradStudent, slug=grad_slug, program__unit__in=request.units) statuses = GradStatus.objects.filter(student=grad) # remove obsolete statuses from the list (but not the model, so legacy data displays properly) status_choices = [(k,v) for k,v in STATUS_CHOICES if k not in STATUS_OBSOLETE] if request.method == 'POST': form = GradStatusForm(request.POST) form.fields['status'].choices = status_choices if form.is_valid(): # Save new status status = form.save(commit=False) status.student = grad status.save() #change gradstudent's last updated/by info to newest grad.updated_at = datetime.datetime.now() grad.created_by = request.user.username grad.save() messages.success(request, "Updated Status History for %s." % (grad.person)) l = LogEntry(userid=request.user.username, description="Updated Status History for %s." % (grad.person), related_object=status) l.save() return HttpResponseRedirect(reverse('grad:manage_status', kwargs={'grad_slug':grad_slug})) else: form = GradStatusForm(initial={'start': Semester.current(), 'start_date': datetime.datetime.today()}) form.fields['status'].choices = status_choices context = { 'form' : form, 'statuses' : statuses, 'grad' : grad, 'can_edit': True, } return render(request, 'grad/manage_status.html', context)
def get_bad_gpa(self): current_semester = Semester.current() semesters = [current_semester.name, current_semester.offset_name(-1), current_semester.offset_name(-2)] cmpt_acad_progs, eng_acad_progs = get_fas_programs() cmpt_gpas = BadGPAsQuery(query_args={ 'acad_progs': cmpt_acad_progs, 'strms': semesters, 'gpa': '2.4', }) low_gpas = cmpt_gpas.result() self.artifacts.append(low_gpas) rows = low_gpas.rows rows.sort() groups = itertools.groupby(rows, CSGenderExplorationReport.group_bin) out_rows = [[prog_gpa[0], prog_gpa[1], prog_gpa[2], len(list(students))] for prog_gpa, students in groups] bins = Table() bins.append_column('ACAD_PROG_PRIMARY') bins.append_column('GENDER') bins.append_column('GPA') bins.append_column('COUNT') bins.rows = out_rows self.artifacts.append(bins)
def create_ta_ra(): """ Build test data for the ta and ra modules. """ from ta.models import CourseDescription, TAPosting, TAApplication, CoursePreference, TAContract, TACourse from ta.models import TAKEN_CHOICES, EXPER_CHOICES from ra.models import Account, Project, SemesterConfig, RAAppointment from ra.models import HIRING_CATEGORY_CHOICES, HIRING_CATEGORY_DISABLED # TAs d = Person.objects.get(userid='dzhao') unit = Unit.objects.get(slug='cmpt') r1 = Role(person=d, role='TAAD', unit=unit) r1.save() r2 = Role(person=d, role='FUND', unit=unit) r2.save() s = Semester.current().next_semester() admin = Person.objects.get(userid='dixon') CourseDescription(unit=unit, description="Office/Marking", labtut=False).save() CourseDescription(unit=unit, description="Office/Marking/Lab", labtut=True).save() a = Account(account_number=12345, position_number=12345, title='MSc TA', unit=unit) a.save() a = Account(account_number=12346, position_number=12346, title='PhD TA', unit=unit) a.save() a = Account(account_number=12347, position_number=12347, title='External TA', unit=unit) a.save() a = Account(account_number=12348, position_number=12348, title='Undergrad TA', unit=unit) a.save() post = TAPosting(semester=s, unit=unit) post.opens = s.start - datetime.timedelta(100) post.closes = s.start - datetime.timedelta(20) post.set_salary([972,972,972,972]) post.set_scholarship([135,340,0,0]) post.set_accounts([Account.objects.get(account_number=12345).id, Account.objects.get(account_number=12346).id, Account.objects.get(account_number=12347).id, Account.objects.get(account_number=12348).id]) post.set_start(s.start) post.set_end(s.end) post.set_deadline(s.start - datetime.timedelta(10)) post.set_payperiods(7.5) post.set_contact(admin.id) post.set_offer_text("This is **your** TA öffer.\n\nThere are various conditions that are töö numerous to list here.") post.save() offerings = list(post.selectable_offerings()) for p in Person.objects.filter(last_name='Grad'): app = TAApplication(posting=post, person=p, category=random.choice(['GTA1','GTA2']), current_program='CMPT', sin='123456789', base_units=random.choice([3,4,5])) app.save() will_ta = [] for i,o in enumerate(random.sample(offerings, 5)): t = random.choice(TAKEN_CHOICES)[0] e = random.choice(EXPER_CHOICES)[0] cp = CoursePreference(app=app, course=o.course, rank=i+1, taken=t, exper=e) cp.save() if random.random() < 0.07*(5-i): will_ta.append(o) if will_ta and random.random() < 0.75: c = TAContract(status=random.choice(['NEW','OPN','ACC'])) c.first_assign(app, post) c.save() for o in will_ta: tac = TACourse(course=o, contract=c, bu=app.base_units) tac.description = tac.default_description() tac.save() # RAs s = Semester.current() superv = list(m.person for m in Member.objects.filter(role='INST').select_related('person')) empl = list(itertools.chain(Person.objects.filter(last_name='Grad'), random.sample(Person.objects.filter(last_name='Student'), 10))) cats = [c for c,d in HIRING_CATEGORY_CHOICES if c not in HIRING_CATEGORY_DISABLED] config = SemesterConfig.get_config([unit], s) acct = Account(account_number=12349, position_number=12349, title='NSERC RA', unit=unit) acct.save() proj1 = Project(project_number=987654, fund_number=31, unit=unit) proj1.save() proj2 = Project(project_number=876543, fund_number=13, unit=unit) proj2.save() for i in range(30): p = random.choice(empl) s = random.choice(superv) c = random.choice(cats) freq = random.choice(['B', 'L']) if freq == 'B': payargs = {'lump_sum_pay': 10000, 'biweekly_pay': 1250, 'pay_periods': 8, 'hourly_pay': 31, 'hours': 40} else: payargs = {'lump_sum_pay': 4000, 'biweekly_pay': 0, 'pay_periods': 8, 'hourly_pay': 0, 'hours': 0} ra = RAAppointment(person=p, sin=123456789, hiring_faculty=s, unit=unit, hiring_category=c, project=random.choice([proj1,proj2]), account=acct, pay_frequency=freq, start_date=config.start_date(), end_date=config.end_date(), **payargs) ra.set_use_hourly(random.choice([True, False])) ra.save() return itertools.chain( [r1, r2], Account.objects.all(), Project.objects.all(), SemesterConfig.objects.all(), RAAppointment.objects.all(), TAPosting.objects.all(), CourseDescription.objects.all(), TAApplication.objects.all(), CoursePreference.objects.all(), TAContract.objects.all(), TACourse.objects.all(), )
from coredata.models import Semester from django.conf import settings # import grads from these units (but CMPT gets special treatment) IMPORT_UNIT_SLUGS = ['cmpt', 'ensc', 'mse', 'psyc'] # in ps_acad_prog dates within about this long of the semester start are actually things that happen next semester DATE_OFFSET = datetime.timedelta(days=30) # ...even longer for dates of things that are startup-biased (like returning from leave) DATE_OFFSET_START = datetime.timedelta(days=90) SIMS_SOURCE = 'sims_source' # key in object.config to record where things came from # don't even query data before this if settings.DEPLOY_MODE in ['devel', 'proddev']: IMPORT_START_SEMESTER = Semester.current().offset_name( -6) # devel/test data doesn't go too far back in time else: IMPORT_START_SEMESTER = '0901' IMPORT_START_DATE = Semester.start_end_dates( Semester.objects.get(name=IMPORT_START_SEMESTER))[0] # if we find students starting before this semester, don't import if settings.DEPLOY_MODE in ['devel', 'proddev']: RELEVANT_PROGRAM_START = Semester.current().offset_name( -6) # devel/test data doesn't go too far back in time else: RELEVANT_PROGRAM_START = '1031' # before this, we aren't going to worry about it. RELEVANT_DATA_START = datetime.date(1993, 9, 1)
def run(self): AcceptedStudentsQuery = AcceptedQuery({ 'strm': Semester.current().offset_name(1), 'acad_plans': [ 'CMPTMAJ', 'DCMPT', 'CMPTMIN', 'CMPTHON', 'CMPTJMA', 'CMPTJHO', 'SOSYMAJ', 'ZUSFU' ] }) AcceptedStudents = AcceptedStudentsQuery.result() EnrolledStudentsQuery = EnrolledQuery({ 'strm': Semester.current().offset_name(1), 'acad_progs': ['CMPT', 'CMPT2'] }) EnrolledStudents = EnrolledStudentsQuery.result() # Let's calculate our totals so we can display those numbers as well. accepted_list = AcceptedStudents.column_as_list("SEX") accepted_total = len(accepted_list) accepted_m_count = len([i for i in accepted_list if i == 'M']) accepted_f_count = len([i for i in accepted_list if i == 'F']) accepted_u_count = len([i for i in accepted_list if i == 'U']) enrolled_list = EnrolledStudents.column_as_list("SEX") enrolled_total = len(enrolled_list) enrolled_m_count = len([i for i in enrolled_list if i == 'M']) enrolled_f_count = len([i for i in enrolled_list if i == 'F']) enrolled_u_count = len([i for i in enrolled_list if i == 'U']) # Let's create two new tables to display these results. accepted_totals = Table() accepted_totals.append_column('TOTAL_COUNT') accepted_totals.append_column('M_COUNT') accepted_totals.append_column('M_PERCENT') accepted_totals.append_column('F_TOTAL') accepted_totals.append_column('F_PERCENT') accepted_totals.append_column('U_COUNT') accepted_totals.append_column('U_PERCENT') accepted_totals.append_row([ accepted_total, accepted_m_count, 100.0 * accepted_m_count / accepted_total, accepted_f_count, 100.0 * accepted_f_count / accepted_total, accepted_u_count, 100.0 * accepted_u_count / accepted_total ]) enrolled_totals = Table() enrolled_totals.append_column('TOTAL_COUNT') enrolled_totals.append_column('M_COUNT') enrolled_totals.append_column('M_PERCENT') enrolled_totals.append_column('F_TOTAL') enrolled_totals.append_column('F_PERCENT') enrolled_totals.append_column('U_COUNT') enrolled_totals.append_column('U_PERCENT') enrolled_totals.append_row([ enrolled_total, enrolled_m_count, 100.0 * enrolled_m_count / enrolled_total, enrolled_f_count, 100.0 * enrolled_f_count / enrolled_total, enrolled_u_count, 100.0 * enrolled_u_count / enrolled_total ]) self.artifacts.append(AcceptedStudents) self.artifacts.append(accepted_totals) self.artifacts.append(EnrolledStudents) self.artifacts.append(enrolled_totals)
def view_doc(request, doc_slug): context = {'BASE_ABS_URL': settings.BASE_ABS_URL} # set up useful context variables for this doc if doc_slug in ["submission", "pages-api"]: instructor = Member.objects.filter( person__userid=request.user.username, offering__graded=True, role__in=["INST", "TA"]) offerings = [m.offering for m in instructor] activities = Activity.objects.filter(offering__in=offerings).annotate( Count('submissioncomponent')).order_by('-offering__semester', '-due_date') # decorate to prefer (1) submission configured, (2) has due date. activities = [(a.submissioncomponent__count == 0, not bool(a.due_date), a) for a in activities] activities.sort() if activities: context['activity'] = activities[0][2] context['course'] = context['activity'].offering elif offerings: context['course'] = offerings[0] else: sem = Semester.current() context['cslug'] = sem.slugform( ) + '-cmpt-001-d1' # a sample contemporary course slug context['userid'] = request.user.username or 'userid' elif doc_slug == "impersonate": instructor = Member.objects.filter( person__userid=request.user.username, offering__graded=True, role__in=["INST", "TA"]) offerings = [(Member.objects.filter(offering=m.offering, role="STUD"), m.offering) for m in instructor] offerings = [(students.count() > 0, course.semester.name, students, course) for students, course in offerings] offerings.sort(key=lambda x: (x[0], x[1], x[3])) offerings.reverse() if offerings: nonempty, semester, students, course = offerings[0] context['course'] = course if students: context['student'] = students[0] else: sem = Semester.current() context['cslug'] = sem.slugform( ) + '-cmpt-001-d1' # a sample contemporary course slug elif doc_slug == "calc_numeric": instructor = Member.objects.filter( person__userid=request.user.username, offering__graded=True, role__in=["INST", "TA"]) offering_ids = [m.offering.id for m in instructor] offerings = CourseOffering.objects.filter( id__in=offering_ids).annotate(Count('activity')) # decorate to prefer (1) recent offerings, (2) many activities offerings = [(o.semester, o.activity__count, o) for o in offerings if o.activity__count > 0] offerings.sort() if offerings: sem, count, course = offerings[0] context['course'] = course activities = NumericActivity.objects.filter(offering=course, deleted=False) context['activities'] = activities if activities.count() > 1: context['act1'] = activities[0] context['act2'] = activities[1] elif activities.count() > 0: context['act1'] = activities[0] context['act2'] = None else: context['act1'] = None context['act2'] = None else: context['course'] = None context['act1'] = None context['act2'] = None elif doc_slug == "search": context['two_years'] = datetime.date.today().year - 2 try: res = render(request, "docs/doc_" + doc_slug + ".html", context) except TemplateDoesNotExist: raise Http404 return res
def import_semester_info(verbose=False, dry_run=False, long_long_ago=False, bootstrap=False): """ Update information on Semester objects from SIMS Finding the reference is tricky. Try Googling 'sfu calendar {{year}} "academic dates"' long_long_ago: import from the beginning of time bootstrap: don't assume Semester.current() will work, for bootstrapping test data creation """ output = [] semester_start = semester_first_day() semester_end = semester_last_day() sims_holidays = all_holidays() if not bootstrap: # we want semesters 5 years into the future: that's a realistic max horizon for grad promises current = Semester.current() strms = [current.offset_name(i) for i in range(15)] else: strms = [] if long_long_ago: strms = sorted(list(set(strms) | set(semester_start.keys()))) semesters = dict( (s.name, s) for s in Semester.objects.filter(name__in=strms)) semester_weeks = itertools.groupby( SemesterWeek.objects.filter( semester__name__in=strms).select_related('semester'), lambda sw: sw.semester.name) semester_weeks = dict((k, list(v)) for k, v in semester_weeks) holidays = itertools.groupby( Holiday.objects.filter(semester__name__in=strms, holiday_type='FULL').select_related('semester'), lambda h: h.semester.name) holidays = dict((k, list(v)) for k, v in holidays) for strm in strms: url = settings.BASE_ABS_URL + reverse('sysadmin:edit_semester', kwargs={'semester_name': strm}) # Semester object try: semester = semesters[strm] except KeyError: semester = Semester(name=strm) semesters[strm] = semester output.append("Creating %s." % (strm, )) # class start and end dates try: start = semester_start[strm] except KeyError: # No data found about this semester: if there's a date already around, honour it # Otherwise, guess "same day as this semester last year" which is probably wrong but close. start = semester.start if not semester.start: lastyr = semesters[semester.offset_name(-3)] start = lastyr.start.replace(year=lastyr.start.year + 1) output.append("Guessing start date for %s." % (strm, )) try: end = semester_end[strm] except KeyError: # no classes scheduled yet? Assume 13 weeks exactly end = start + datetime.timedelta(days=91) if semester.start != start: output.append("Changing start date for %s from %s to %s." % (strm, semester.start, start)) semester.start = start if semester.end != end: output.append("Changing end date for %s from %s to %s." % (strm, semester.end, end)) semester.end = end if not dry_run: semester.save() # SemesterWeeks weeks = semester_weeks.get(strm, []) if not weeks: sw = SemesterWeek(semester=semester, week=1, monday=first_monday(start)) weeks.append(sw) assert sw.monday.weekday() == 0 output.append("Creating week 1 for %s on %s." % (strm, sw.monday)) if not dry_run: sw.save() elif weeks[0].monday != first_monday(start): sw = weeks[0] sw.monday = first_monday(start) output.append("Changing first Monday of %s to %s." % (strm, sw.monday)) if not dry_run: sw.save() length = semester.end - semester.start if not bootstrap and length > datetime.timedelta(days=92) and len(weeks) < 2 \ and semester.start - datetime.date.today() < datetime.timedelta(days=365): # semester is longer than 13 weeks: insist that the user specify reading week reasonably-soon before the semester starts message = "Semester %s is long (%s) but has no reading week specified. Please have a look here: %s\n\nYou probably want to enter the Monday of week 5/6/7/8 as the Monday after reading week, a week later than it would otherwise be." % ( strm, length, url) if verbose: output.append('*** ' + message) else: import_admin_email( source='coredata.importer.import_semester_info', message=message) elif not bootstrap: # also check that the last day of classes is at a coherent time. Might reveal problems with reading week specification. endweek, _ = semester.week_weekday(semester.end, weeks=weeks) if endweek not in [12, 13, 14]: message = "Semester %s ends in week %i (should be 13 or 14). That's weird. Have a look here to see if things are coherent: %s" % ( strm, endweek, url) if verbose: output.append('*** ' + message) else: import_admin_email( source='coredata.importer.import_semester_info', message=message) # Holidays hs = holidays.get(strm, []) h_start, h_end = Semester.start_end_dates(semester) for dt, desc in [(d, h) for d, h in sims_holidays if h_start <= d <= h_end]: existing = [h for h in hs if h.date == dt] if existing: holiday = existing[0] else: holiday = Holiday(semester=semester, date=dt, holiday_type='FULL') output.append("Adding holiday %s on %s." % (desc, dt)) holiday.description = desc if not dry_run: holiday.save() if verbose: print('\n'.join(output))
def view_doc(request, doc_slug): context = {'BASE_ABS_URL': settings.BASE_ABS_URL} # set up useful context variables for this doc if doc_slug in ["submission", "pages-api"]: instructor = Member.objects.filter(person__userid=request.user.username, offering__graded=True, role__in=["INST","TA"]) offerings = [m.offering for m in instructor] activities = Activity.objects.filter(offering__in=offerings).annotate(Count('submissioncomponent')).order_by('-offering__semester', '-due_date') # decorate to prefer (1) submission configured, (2) has due date. activities = [(a.submissioncomponent__count==0, not bool(a.due_date), a) for a in activities] activities.sort() if activities: context['activity'] = activities[0][2] context['course'] = context['activity'].offering elif offerings: context['course'] = offerings[0] else: sem = Semester.current() context['cslug'] = sem.slugform() + '-cmpt-001-d1' # a sample contemporary course slug context['userid'] = request.user.username or 'userid' elif doc_slug == "impersonate": instructor = Member.objects.filter(person__userid=request.user.username, offering__graded=True, role__in=["INST","TA"]) offerings = [(Member.objects.filter(offering=m.offering, role="STUD"), m.offering) for m in instructor] offerings = [(students.count()>0, course.semester.name, students, course) for students, course in offerings] offerings.sort(key=lambda x: (x[0], x[1], x[3])) offerings.reverse() if offerings: nonempty, semester, students, course = offerings[0] context['course'] = course if students: context['student'] = students[0] else: sem = Semester.current() context['cslug'] = sem.slugform() + '-cmpt-001-d1' # a sample contemporary course slug elif doc_slug == "calc_numeric": instructor = Member.objects.filter(person__userid=request.user.username, offering__graded=True, role__in=["INST","TA"]) offering_ids = [m.offering.id for m in instructor] offerings = CourseOffering.objects.filter(id__in=offering_ids).annotate(Count('activity')) # decorate to prefer (1) recent offerings, (2) many activities offerings = [(o.semester, o.activity__count, o) for o in offerings if o.activity__count>0] offerings.sort() if offerings: sem, count, course = offerings[0] context['course'] = course activities = NumericActivity.objects.filter(offering=course, deleted=False) context['activities'] = activities if activities.count() > 1: context['act1'] = activities[0] context['act2'] = activities[1] elif activities.count() > 0: context['act1'] = activities[0] context['act2'] = None else: context['act1'] = None context['act2'] = None else: context['course'] = None context['act1'] = None context['act2'] = None elif doc_slug == "search": context['two_years'] = datetime.date.today().year - 2 try: res = render(request, "docs/doc_" + doc_slug + ".html", context) except TemplateDoesNotExist: raise Http404 return res
def run(self): current_semester = Semester.current() # Get all active CMPT PhD students, since that's all we care about. program = GradProgram.objects.get(label="PhD", unit__label='CMPT') all_students = GradStudent.objects.filter(program=program, current_status='ACTI') senior_supervisors = Supervisor.objects.filter(student__in=all_students, supervisor_type='SEN', removed=False) potential_supervisors = Supervisor.objects.filter(student__in=all_students, supervisor_type='POT', removed=False) # Split them up between the 3 tables we want: table1_students = all_students.filter(start_semester__lte=current_semester.offset(-2)) table2_students = all_students.filter(start_semester__lte=current_semester.offset(-5)) table3_students = all_students.filter(start_semester__lte=current_semester.offset(-8)) # The GradRequirements we care about: requirement1 = GradRequirement.objects.get(program=program, description='Supervisory Committee') requirement2 = GradRequirement.objects.get(program=program, description='Depth Exam') requirement3 = GradRequirement.objects.get(program=program, description='Breadth Requirements Approved') requirement4 = GradRequirement.objects.get(program=program, description='Thesis Proposal') # All three tables will have the same columns, might as well create them quickly. table1 = Table() table2 = Table() table3 = Table() for table in [table1, table2, table3]: table.append_column("Name") table.append_column("Student ID") table.append_column("Email") table.append_column("Semester Count") table.append_column("Senior Supervisor") table3.append_column("Missing Requirement(s)") # A quick helper method to build the string to display for the Senior Supervisor, given a student def get_supervisor_string(student): supervisor = senior_supervisors.filter(student=student).first() if supervisor: return '%s <%s>' % (supervisor.supervisor.name(), supervisor.supervisor.email()) else: supervisor = potential_supervisors.filter(student=student).first() if supervisor: return '%s (potential) <%s>' % (supervisor.supervisor.name(), supervisor.supervisor.email()) else: return 'None' # Get the lists of students from the master list who have completed the various requirements. students1_completed = CompletedRequirement.objects.values_list('student', flat=True)\ .filter(requirement=requirement1, student__in=all_students, removed=False) students2_completed = CompletedRequirement.objects.values_list('student', flat=True) \ .filter(requirement=requirement2, student__in=all_students, removed=False) students3_completed = CompletedRequirement.objects.values_list('student', flat=True) \ .filter(requirement=requirement3, student__in=all_students, removed=False) # The 4th requirement only really applies to the third list, so might as well limit it: students4_completed = CompletedRequirement.objects.values_list('student', flat=True) \ .filter(requirement=requirement4, student__in=table3_students, removed=False) # First table, simply everyone in table1_students who doesn't have a completed requirement 1 for student in [s for s in table1_students if s.id not in students1_completed]: supervisor_string = get_supervisor_string(student) table1.append_row([student.person.name(), student.person.emplid, student.person.email(), current_semester - student.start_semester + 1, supervisor_string]) # Table 2 is also pretty easy, just add everyone who is is missing both of requirements 2 & 3. for student in [s for s in table2_students if s.id not in students2_completed and s.id not in students3_completed]: supervisor_string = get_supervisor_string(student) table2.append_row([student.person.name(), student.person.emplid, student.person.email(), current_semester - student.start_semester + 1, supervisor_string]) # Table 3 will require a bit more work, since we want to also display what requirements aren't met. # First, establish our target students: students3 = [s for s in table3_students if s.id not in students2_completed or s.id not in students3_completed or s.id not in students4_completed] for student in students3: # Build the string telling us which requirement is missing. Stupid, but has to be done. missing_str_list = [] requirement_to_list = [(requirement2, students2_completed), (requirement3, students3_completed), (requirement4, students4_completed)] for requirement, student_list in requirement_to_list: if student.id not in student_list: missing_str_list.append(requirement.description) missing_str = '; '.join(missing_str_list) supervisor_string = get_supervisor_string(student) table3.append_row([student.person.name(), student.person.emplid, student.person.email(), current_semester - student.start_semester + 1, supervisor_string, missing_str]) for table in [table1, table2, table3]: self.artifacts.append(table)
from coredata.models import Semester from django.conf import settings # import grads from these units (but CMPT gets special treatment) IMPORT_UNIT_SLUGS = ['cmpt', 'ensc', 'mse', 'psyc'] # in ps_acad_prog dates within about this long of the semester start are actually things that happen next semester DATE_OFFSET = datetime.timedelta(days=30) # ...even longer for dates of things that are startup-biased (like returning from leave) DATE_OFFSET_START = datetime.timedelta(days=90) SIMS_SOURCE = 'sims_source' # key in object.config to record where things came from # don't even query data before this if settings.DEPLOY_MODE in ['devel', 'proddev']: IMPORT_START_SEMESTER = Semester.current().offset_name(-6) # devel/test data doesn't go too far back in time else: IMPORT_START_SEMESTER = '0901' IMPORT_START_DATE = Semester.start_end_dates(Semester.objects.get(name=IMPORT_START_SEMESTER))[0] # if we find students starting before this semester, don't import if settings.DEPLOY_MODE in ['devel', 'proddev']: RELEVANT_PROGRAM_START = Semester.current().offset_name(-6) # devel/test data doesn't go too far back in time else: RELEVANT_PROGRAM_START = '1031' # before this, we aren't going to worry about it. RELEVANT_DATA_START = datetime.date(1993, 9, 1) # be even more conservative for CMPT: this is when we started getting slightly cleaner data including adm_appl_nbr
def global_data(self): univ, _ = Unit.objects.get_or_create(label='UNIV', name='Simon Fraser University', parent=None) fas, _ = Unit.objects.get_or_create(label='FAS', name='Faculty of Applied Sciences', parent=univ) fas.config['informal_name'] = 'Applied Sciences' fas.save() cmpt, _ = Unit.objects.get_or_create(label='CMPT') cmpt.name = 'School of Computing Science' cmpt.config['informal_name'] = 'Computing Science' cmpt.parent = fas cmpt.save() ensc, _ = Unit.objects.get_or_create(label='ENSC') ensc.name = 'School of Engineering Science' ensc.config['informal_name'] = 'Engineering Science' ensc.parent = fas ensc.save() mse, _ = Unit.objects.get_or_create(label='MSE') mse.name = 'Mechatronic Systems Engineering' mse.config['informal_name'] = 'Mechatronics' mse.parent = fas mse.save() phil, _ = Unit.objects.get_or_create(label='PHIL') phil.name = 'Department of Philosophy' phil.parent = None phil.save() create_fake_semester('1134') create_fake_semester('1137') create_fake_semester('1141') create_fake_semester('1144') create_fake_semester('1147') danyu = get_or_create_nosave(Person, userid='dzhao', first_name='DanYu', last_name='Zhao') danyu.emplid = 220000123 danyu.save() greg = get_or_create_nosave(Person, userid='ggbaker', first_name='Gregory', last_name='Baker') greg.emplid = 220000124 greg.save() diana = get_or_create_nosave(Person, userid='diana', first_name='Diana', last_name='Cukierman') diana.emplid = 220000125 diana.save() tony = get_or_create_nosave(Person, userid='dixon', first_name='Anthony', last_name='Dixon') tony.emplid = 220000126 tony.save() brad = get_or_create_nosave(Person, userid='bbart', first_name='Bradley', last_name='Bart') brad.emplid = 220000127 brad.save() farid = get_or_create_nosave(Person, userid='mfgolnar', first_name='Farid', last_name='Golnaraghi') farid.emplid = 220000128 farid.save() phillip = get_or_create_nosave(Person, userid='phillip', first_name='Phillip', last_name='Philosophy') phillip.emplid = 220000129 phillip.save() try: o = CourseOffering.objects.get(slug=TEST_COURSE_SLUG) except CourseOffering.DoesNotExist: o = CourseOffering(slug=TEST_COURSE_SLUG, semester=Semester.current(), subject='CMPT', number='123', enrl_cap=10, enrl_tot=5, wait_tot=0) o.save() m, _ = Member.objects.get_or_create(person=greg, offering=o, role='INST') m.added_reason = 'AUTO' m.save()
def import_strms(): s = Semester.current() return [s.name, s.offset_name(1), s.offset_name(2)]
def run(self): sems = Semester.objects.filter(name__gte='1101', name__lte=Semester.current().name) u = Unit.objects.filter(label__in=['CMPT', 'MSE', 'ENSC']) courses = CourseOffering.objects.prefetch_related( 'meeting_time').filter( semester__in=sems, owner__in=u, graded=True).exclude( flags=CourseOffering.flags.combined).exclude( subject='DDP').order_by('semester', 'subject', 'number') instructors = Member.objects.filter(role='INST', added_reason='AUTO', offering__in=courses) \ .exclude(offering__component='CAN') \ .order_by('person__last_name', 'person__first_name', 'offering__semester__name') course_history = Table() course_history.append_column('Instructor') course_history.append_column('First Teaching Semester (>=1101)') course_history.append_column('Last Teaching Semester') course_history.append_column('Current Rank') course_history.append_column('School') course_history.append_column('Teaching Credits') course_history.append_column('Mean Headcount') course_history.append_column('Crs per Year') course_history.append_column('Unique Crs') course_history.append_column('Crs Levels') for i, memberships in itertools.groupby(instructors, key=lambda i: i.person): memberships = [m for m in memberships if m.teaching_credit() > 0] if i is None or not memberships: continue instr = i.sortname() first_semester = memberships[0].offering.semester last_semester = memberships[-1].offering.semester rank = CareerEvent.current_ranks(i.id) roles = Role.objects.filter(person=i, role='FAC').select_related('unit') unit = ', '.join(r.unit.label for r in roles) if rank == 'unknown': rank = 'non-faculty' if unit == '': unit = ', '.join(set(m.offering.subject for m in memberships)) offerings = [m.offering for m in memberships] num_offerings = float(sum(m.teaching_credit() for m in memberships)) headcount = sum(o.enrl_tot for o in offerings) duration = last_semester - first_semester + 1 levels = sorted(list(set(str(o.number)[0] for o in offerings))) unique = len(set(o.course_id for o in offerings)) course_history.append_row([ instr, first_semester.name, last_semester.name, rank, unit, round(num_offerings, 2), round(headcount / num_offerings, 1), round(num_offerings / duration * 3, 1), unique, ','.join(levels) ]) self.artifacts.append(course_history)
def test_semester(): return Semester.current().offset(1)
def create_ta_ra(): """ Build test data for the ta and ra modules. """ from ta.models import CourseDescription, TAPosting, TAApplication, CoursePreference, TAContract, TACourse from ta.models import TAKEN_CHOICES, EXPER_CHOICES from ra.models import Account, Project, SemesterConfig, RAAppointment from ra.models import HIRING_CATEGORY_CHOICES, HIRING_CATEGORY_DISABLED # TAs d = Person.objects.get(userid='dzhao') unit = Unit.objects.get(slug='cmpt') r1 = Role(person=d, role='TAAD', unit=unit) r1.save() r2 = Role(person=d, role='FUND', unit=unit) r2.save() s = Semester.current().next_semester() admin = Person.objects.get(userid='dixon') CourseDescription(unit=unit, description="Office/Marking", labtut=False).save() CourseDescription(unit=unit, description="Office/Marking/Lab", labtut=True).save() a = Account(account_number=12345, position_number=12345, title='MSc TA', unit=unit) a.save() a = Account(account_number=12346, position_number=12346, title='PhD TA', unit=unit) a.save() a = Account(account_number=12347, position_number=12347, title='External TA', unit=unit) a.save() a = Account(account_number=12348, position_number=12348, title='Undergrad TA', unit=unit) a.save() post = TAPosting(semester=s, unit=unit) post.opens = s.start - datetime.timedelta(100) post.closes = s.start - datetime.timedelta(20) post.set_salary([972,972,972,972]) post.set_scholarship([135,340,0,0]) post.set_accounts([Account.objects.get(account_number=12345).id, Account.objects.get(account_number=12346).id, Account.objects.get(account_number=12347).id, Account.objects.get(account_number=12348).id]) post.set_start(s.start) post.set_end(s.end) post.set_deadline(s.start - datetime.timedelta(10)) post.set_payperiods(7.5) post.set_contact(admin.id) post.set_offer_text("This is **your** TA offer.\n\nThere are various conditions that are too numerous to list here.") post.save() offerings = list(post.selectable_offerings()) for p in Person.objects.filter(last_name='Grad'): app = TAApplication(posting=post, person=p, category=random.choice(['GTA1','GTA2']), current_program='CMPT', sin='123456789', base_units=random.choice([3,4,5])) app.save() will_ta = [] for i,o in enumerate(random.sample(offerings, 5)): t = random.choice(TAKEN_CHOICES)[0] e = random.choice(EXPER_CHOICES)[0] cp = CoursePreference(app=app, course=o.course, rank=i+1, taken=t, exper=e) cp.save() if random.random() < 0.07*(5-i): will_ta.append(o) if will_ta and random.random() < 0.75: c = TAContract(status=random.choice(['NEW','OPN','ACC'])) c.first_assign(app, post) c.save() for o in will_ta: tac = TACourse(course=o, contract=c, bu=app.base_units) tac.description = tac.default_description() tac.save() # RAs s = Semester.current() superv = list(m.person for m in Member.objects.filter(role='INST').select_related('person')) empl = list(itertools.chain(Person.objects.filter(last_name='Grad'), random.sample(Person.objects.filter(last_name='Student'), 10))) cats = [c for c,d in HIRING_CATEGORY_CHOICES if c not in HIRING_CATEGORY_DISABLED] config = SemesterConfig.get_config([unit], s) acct = Account(account_number=12349, position_number=12349, title='NSERC RA', unit=unit) acct.save() proj1 = Project(project_number=987654, fund_number=31, unit=unit) proj1.save() proj2 = Project(project_number=876543, fund_number=13, unit=unit) proj2.save() for i in range(30): p = random.choice(empl) s = random.choice(superv) c = random.choice(cats) freq = random.choice(['B', 'L']) if freq == 'B': payargs = {'lump_sum_pay': 10000, 'biweekly_pay': 1250, 'pay_periods': 8, 'hourly_pay': 31, 'hours': 40} else: payargs = {'lump_sum_pay': 4000, 'biweekly_pay': 0, 'pay_periods': 8, 'hourly_pay': 0, 'hours': 0} ra = RAAppointment(person=p, sin=123456789, hiring_faculty=s, unit=unit, hiring_category=c, project=random.choice([proj1,proj2]), account=acct, pay_frequency=freq, start_date=config.start_date(), end_date=config.end_date(), **payargs) ra.set_use_hourly(random.choice([True, False])) ra.save() return itertools.chain( [r1, r2], Account.objects.all(), Project.objects.all(), SemesterConfig.objects.all(), RAAppointment.objects.all(), TAPosting.objects.all(), CourseDescription.objects.all(), TAApplication.objects.all(), CoursePreference.objects.all(), TAContract.objects.all(), TACourse.objects.all(), )
def import_strms(): s = Semester.current() return [s.name, s.offset_name(1), s.offset_name(2), s.offset_name(3), s.offset_name(4), s.offset_name(5), s.offset_name(6), s.offset_name(7), s.offset_name(8), s.offset_name(9)]
def get_timeline(emplid, verbose=False): """ For the student with emplid, Get a list of programs, start and end semester [{'program_code':'CPPHD', 'start':1111, 'end':1137, 'on leave':['1121', '1124']) ] * will include an 'adm_appl_nbr' if an admission record can be found with that program """ programs = get_student_programs(emplid) if verbose: print "----------" for program in programs: print program # calculate start and end date for programs prog_dict = {} for program_code, strm, unt_taken in programs: if program_code not in prog_dict: prog_dict[program_code] = {'start':'9999', 'end':'1111', 'not_on_leave':[]} if int(strm) < int(prog_dict[program_code]['start']): prog_dict[program_code]['start'] = strm elif int(strm) > int(prog_dict[program_code]['end']): prog_dict[program_code]['end'] = strm if float(unt_taken) >= 0.1: prog_dict[program_code]['not_on_leave'].append(strm) if verbose: print "----------" for key, val in prog_dict.iteritems(): print key, val # calculate on-leave semesters on_leave_semesters = [strm for strm, reason in get_on_leave_semesters(emplid)] try: for program_code, program_object in prog_dict.iteritems(): prog_dict[program_code]['on_leave'] = [] semesters = Semester.range( program_object['start'], program_object['end'] ) for semester in semesters: if (int(semester) <= int(Semester.current().name) and (semester in on_leave_semesters or semester not in program_object['not_on_leave'])): prog_dict[program_code]['on_leave'].append(semester) prog_dict[program_code]['on_leave'].sort() except Semester.DoesNotExist: print "Semester out of range", program_object['start'], program_object['end'] return {} # put the programs in a list, sorted by start date programs = [] for program_code, program_object in prog_dict.iteritems(): del program_object['not_on_leave'] program_object['program_code'] = program_code programs.append(program_object) programs = sorted( programs, key= lambda x : int(x['start']) ) if verbose: print "----------" for program in programs: print program # how did it end? for program in programs: hdie = get_end_of_degree(emplid, program['program_code'], program['start']) if hdie: program['how_did_it_end'] = { 'code':hdie[0], 'reason':hdie[1], 'date':hdie[2], 'semester': str(Semester.get_semester(hdie[2]).name) } if int(program['how_did_it_end']['semester']) < int(program['end']): program['end'] = program['how_did_it_end']['semester'] # for every previous program, create an end-date and cut off all on-leave semesters # at the beginning of the next program in the list. for program, next_program in pairs(programs): if int(program['end']) > int(next_program['start']): program['end'] = next_program['start'] for on_leave in program['on_leave']: if int(on_leave) > int(program['end']): program['on_leave'].remove(on_leave) # group the on-leave semesters for program in programs: on_leave = [] if len(program['on_leave']) > 0: last_group = (program['on_leave'][0], program['on_leave'][0]) last_group_pushed = False for semester in program['on_leave']: if semester in last_group or int(semester) > int(program['end']): continue if semester == lazy_next_semester(last_group[1]): last_group = ( last_group[0], semester ) last_group_pushed = False else: on_leave.append(last_group) last_group = (semester, semester) last_group_pushed = True if not last_group_pushed: on_leave.append(last_group) program['on_leave'] = on_leave # does this program have admission records? for program in programs: adm_appl_nbrs = guess_adm_appl_nbr(emplid, program['program_code'], program['start'], program['end'] ) if len(adm_appl_nbrs) > 0: program['adm_appl_nbr'] = str(adm_appl_nbrs[0]) program['admission_records'] = get_admission_records(emplid, program['adm_appl_nbr']) else: adm_appl_nbrs = guess_harder_at_adm_appl_nbr(emplid, program['program_code'], program['start'], program['end'] ) if len(adm_appl_nbrs) > 0: program['adm_appl_nbr'] = str(adm_appl_nbrs[0]) program['admission_records'] = get_admission_records(emplid, program['adm_appl_nbr']) else: program['adm_appl_nbr'] = None return programs