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 test_grad_pages(self): """ Check overall pages for the grad module and make sure they all load """ client = Client() client.login_user('dzhao') gs = self.__make_test_grad() prog = gs.program GradRequirement(program=prog, description="Some New Requirement").save() Supervisor(student=GradStudent.objects.all()[0], supervisor=Person.objects.get(userid='ggbaker'), supervisor_type='SEN').save() lt = LetterTemplate( unit=gs.program.unit, label='Template', content="This is the\n\nletter for {{first_name}}.") lt.save() test_views(self, client, 'grad.views.', [ 'programs', 'new_program', 'requirements', 'new_requirement', 'letter_templates', 'new_letter_template', 'manage_scholarshipType', 'search', 'funding_report', 'all_promises' ], {}) test_views(self, client, 'grad.views.', ['manage_letter_template'], {'letter_template_slug': lt.slug}) test_views(self, client, 'grad.views.', ['not_found'], {}, qs='search=grad')
def __make_test_grad(self): gs = self.gs 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, start_semester=Semester.current()).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 update_local_data(self, student_info, verbosity, dry_run): # if self.grad_program.unit.slug == 'cmpt': # return key = self.import_key() local_committee = student_info['committee'] sup_type = COMMITTEE_MEMBER_MAP[self.committee_role] # cache People objects, so we don't query for them too much. if self.sup_emplid in CommitteeMembership.found_people: p = CommitteeMembership.found_people[self.sup_emplid] else: p = add_person(self.sup_emplid, external_email=True, commit=(not dry_run)) CommitteeMembership.found_people[self.sup_emplid] = p matches = [ m for m in local_committee if m.supervisor == p and m.supervisor_type == sup_type ] if matches: member = matches[0] else: similar = [m for m in local_committee if m.supervisor == p] if len(similar) > 0: if verbosity > 2: print( "* Found similar (but imperfect) committee member for %s is a %s for %s/%s" % (p.name(), SUPERVISOR_TYPE[sup_type], self.emplid, self.unit.slug)) member = similar[0] else: if verbosity: print("Adding committee member: %s is a %s for %s/%s" % (p.name(), SUPERVISOR_TYPE[sup_type], self.emplid, self.unit.slug)) member = Supervisor(student=student_info['student'], supervisor=p, supervisor_type=sup_type) member.created_at = self.effdt local_committee.append(member) if SIMS_SOURCE not in member.config: # record (the first) place we found this fact member.config[SIMS_SOURCE] = key # if it wasn't the product of a previous import it was hand-entered: take the effdt from SIMS member.created_at = self.effdt # TODO: try to match up external members with new real ones? That sounds hard. # TODO: remove members if added by this import (in the past) and not found in the newest committee version if not dry_run: member.save_if_dirty()
def manage_defence(request, grad_slug): """ Page for managing all defence-related stuff. Slightly complicated since this info cuts across several models. """ grad = get_object_or_404(GradStudent, slug=grad_slug, program__unit__in=request.units) supervisors = Supervisor.objects.filter( student=grad).select_related('supervisor') supervisor_people = [s.supervisor for s in supervisors if s.supervisor] supervisor_choices = possible_supervisors(units=request.units, extras=supervisor_people, null=True) if request.method == 'POST': form = GradDefenceForm(request.POST) form.set_supervisor_choices(supervisor_choices) if form.is_valid(): with transaction.atomic(): grad.config['thesis_type'] = form.cleaned_data['thesis_type'] grad.config['work_title'] = form.cleaned_data['work_title'] grad.config['exam_date'] = form.cleaned_data['exam_date'] grad.config['thesis_outcome'] = form.cleaned_data[ 'thesis_outcome'] grad.config['thesis_location'] = form.cleaned_data[ 'thesis_location'] grad.save() if form.cleaned_data['internal']: p = form.cleaned_data['internal'] # remove any old ones remove_sup = Supervisor.objects.filter( student=grad, removed=False, supervisor_type='SFU').exclude(supervisor=p) for sup in remove_sup: sup.removed = True sup.save() existing_sup = Supervisor.objects.filter( student=grad, removed=False, supervisor_type='SFU', supervisor=p) if not existing_sup: # doesn't exist: create sup = Supervisor(student=grad, supervisor_type='SFU', supervisor=p) sup.save() # else: already there, so nothing to change if form.cleaned_data['chair']: p = form.cleaned_data['chair'] # remove any old ones remove_sup = Supervisor.objects.filter( student=grad, removed=False, supervisor_type='CHA').exclude(supervisor=p) for sup in remove_sup: sup.removed = True sup.save() existing_sup = Supervisor.objects.filter( student=grad, removed=False, supervisor_type='CHA', supervisor=p) if not existing_sup: # doesn't exist: create sup = Supervisor(student=grad, supervisor_type='CHA', supervisor=p) sup.save() # else: already there, so nothing to change if form.cleaned_data['external']: name = form.cleaned_data['external'] # remove any old ones remove_sup = Supervisor.objects.filter( student=grad, removed=False, supervisor_type='EXT').exclude(external=name) for sup in remove_sup: sup.removed = True sup.save() # creqate/update existing_sup = Supervisor.objects.filter( student=grad, removed=False, supervisor_type='EXT', external=name) if existing_sup: sup = existing_sup[0] else: sup = Supervisor(student=grad, supervisor_type='EXT', external=name) sup.config['email'] = form.cleaned_data['external_email'] sup.config['contact'] = form.cleaned_data[ 'external_contact'] sup.config['attend'] = form.cleaned_data['external_attend'] sup.save() messages.success(request, "Updated defence info for %s." % (grad.person)) l = LogEntry(userid=request.user.username, description="Updated grad defence info for %s." % (grad), related_object=grad) l.save() return HttpResponseRedirect( reverse('grad.views.view', kwargs={'grad_slug': grad.slug})) else: initial = {} if 'thesis_type' in grad.config: initial['thesis_type'] = grad.config['thesis_type'] if 'work_title' in grad.config: initial['work_title'] = grad.config['work_title'] if 'exam_date' in grad.config: initial['exam_date'] = grad.config['exam_date'] if 'thesis_outcome' in grad.config: initial['thesis_outcome'] = grad.config['thesis_outcome'] if 'thesis_location' in grad.config: initial['thesis_location'] = grad.config['thesis_location'] internals = Supervisor.objects.filter(student=grad, removed=False, supervisor_type='SFU') if internals: initial['internal'] = internals[0].supervisor_id chairs = Supervisor.objects.filter(student=grad, removed=False, supervisor_type='CHA') if chairs: initial['chair'] = chairs[0].supervisor_id externals = Supervisor.objects.filter(student=grad, removed=False, supervisor_type='EXT') if externals: ext = externals[0] initial['external'] = ext.external initial['external_email'] = ext.config.get('email', '') initial['external_contact'] = ext.config.get('contact', '') initial['external_attend'] = ext.config.get('attend', '') form = GradDefenceForm(initial=initial) form.set_supervisor_choices(supervisor_choices) context = { 'form': form, 'grad': grad, } return render(request, 'grad/manage_defence.html', context)
def process_pcs_row(row, column, rownum, unit, semester, user): """ Process a single row from the PCS import """ appsemester = semester.previous_semester() warnings = [] ident = "in row %i" % (rownum) appid = row[column['appid']] emplid = row[column['emplid']] program = row[column['program']] # get Person, from SIMS if necessary try: p = Person.objects.get(emplid=int(emplid)) except ValueError: warnings.append("Bad emplid %s: not processing that row." % (ident)) return warnings except Person.DoesNotExist: try: p = add_person(emplid) except SIMSProblem as e: return e.message ident = 'for "%s"' % (p.name()) # update information on the Person email = row[column['email']] if email: p.config['applic_email'] = email dob = row[column['dob']] if dob: try: dt = datetime.datetime.strptime(dob, "%Y-%m-%d") p.config['birthdate'] = dt.date().isoformat() except ValueError: warnings.append("Bad birthdate %s." % (ident)) # get extended SIMS data data = grad_student_info(emplid) p.config.update(data) p.save() #print "Importing %s" % (p) # get GradStudent, creating if necessary # a unique identifier for this application, so we can detect repeated imports (and handle gracefully) uid = "%s-%s-%s-%s" % (unit.slug, semester.name, appid, emplid) # TODO: wrong, wrong, wrong. Figure out how to select program from import data program = GradProgram.objects.filter(unit=unit)[0] # find the old GradStudent if possible gss = GradStudent.objects.filter(program__unit=unit, person=p) gs = None for g in gss: if 'app_id' in g.config and g.config['app_id'] == uid: gs = g break if not gs: gs = GradStudent(program=program, person=p) gs.config['app_id'] = uid resarea = row[column['resarea']] firstlang = row[column['firstlang']] gs.research_area = resarea gs.mother_tongue = firstlang gs.created_by = user.userid gs.updated_by = user.userid gs.config['start_semester'] = semester.name gs.save() complete = row[column['complete']].strip() decision = row[column['decision']].strip() notes = row[column['notes']].strip() gs.config['decisionnotes'] = notes old_st = GradStatus.objects.filter(student=gs, start__name__gte=semester.name) if not old_st: # if no old status for current semester, create one # application completion status if complete == 'AppConfirm': st = GradStatus(student=gs, status="COMP", start=appsemester, end=None, notes="PCS import") st.save() elif complete == '': st = GradStatus(student=gs, status="INCO", start=appsemester, end=None, notes="PCS import") st.save() else: warnings.append( 'Unknown "Confirmation of Completion of Application" value %s.' % (ident)) # decision status if decision == 'DECL': st = GradStatus(student=gs, status="DECL", start=appsemester, end=None, notes="PCS import") st.save() elif decision == '': st = GradStatus(student=gs, status="OFFO", start=appsemester, end=None, notes="PCS import") st.save() elif decision == 'R': st = GradStatus(student=gs, status="REJE", start=appsemester, end=None, notes="PCS import") st.save() elif decision == 'HOLD': st = GradStatus(student=gs, status="HOLD", start=appsemester, end=None, notes="PCS import") st.save() elif decision == 'AMScT': # TODO: bump program to MSc thesis st = GradStatus(student=gs, status="CONF", start=appsemester, end=None, notes="PCS import") st.save() elif decision == 'AMScC': # TODO: bump program to MSc course-based st = GradStatus(student=gs, status="CONF", start=appsemester, end=None, notes="PCS import") st.save() # potential supervisor potsuper = row[column['potsuper']] if potsuper: superv = None external = None try: ps_last, ps_first = potsuper.split(', ') except ValueError: warnings.append( 'Bad potential supervisor name %s: will store them as an "external" supervisor.' % (ident)) external = potsuper else: potentials = possible_supervisor_people([unit]) potential_ids = [p.id for p in potentials] query = Q(last_name=ps_last, first_name=ps_first) | Q( last_name=ps_last, pref_first_name=ps_first) people = Person.objects.filter(query, id__in=potential_ids) if people.count() == 1: superv = people[0] else: warnings.append( 'Coundn\'t find potential supervisor %s: will store them as an "external" supervisor.' % (ident)) external = potsuper old_s = Supervisor.objects.filter(student=gs, supervisor_type='POT') if old_s: s = old_s[0] else: s = Supervisor(student=gs, supervisor_type='POT') s.superv = superv s.external = external s.position = 0 s.created_by = user.userid s.modified_by = user.userid s.save() l = LogEntry(userid=user.userid, description="Imported grad record for %s (%s) from PCS" % (p.name(), p.emplid), related_object=gs) l.save() return warnings
def create_grad(): """ Test data for grad, ta, ra """ from grad.models import GradProgram, GradStudent, GradProgramHistory, GradStatus, ScholarshipType, Scholarship, \ OtherFunding, Promise, GradRequirement, CompletedRequirement, LetterTemplate, GradFlag, GradFlagValue, Supervisor cmpt = Unit.objects.get(slug='cmpt') ensc = Unit.objects.get(slug='ensc') mse = Unit.objects.get(slug='mse') # some admin roles d = Person.objects.get(userid='dzhao') r1 = Role(person=d, role='GRAD', unit=cmpt, expiry=role_expiry) r1.save() r2 = Role(person=Person.objects.get(userid='popowich'), role="GRPD", unit=cmpt, expiry=role_expiry) r2.save() roles = [r1, r2] # departmental data st1 = ScholarshipType(unit=cmpt, name='Scholarship-o-rama', eligible=False) st1.save() st2 = ScholarshipType(unit=cmpt, name='Generic Scholarship #8', eligible=True) st2.save() scholarship_types = [st1, st2] templates = [ { "unit": cmpt, "label": "offer", "content": u"Congratulations, {{first_name}}, we would like to offer you admission to the {{program}} program in Computing Science at SFU.\r\n\r\nThis is gööd news. Really." }, { "unit": cmpt, "label": "visa", "content": "This is to confirm that {{title}} {{first_name}} {{last_name}} is currently enrolled as a full time student in the {{program}} in the School of Computing Science at SFU." }, { "unit": cmpt, "label": "Funding", "content": "This is to confirm that {{title}} {{first_name}} {{last_name}} is a student in the School of Computing Science's {{program}} program. {{He_She}} has been employed as follows:\r\n\r\n{% if tafunding %}Teaching assistant responsibilities include providing tutorials, office hours and marking assignments. {{title}} {{last_name}}'s assignments have been:\r\n\r\n{{ tafunding }}{% endif %}\r\n{% if rafunding %}Research assistants assist/provide research services to faculty. {{title}} {{last_name}}'s assignments have been:\r\n\r\n{{ rafunding }}{% endif %}\r\n{% if scholarships %}{{title}} {{last_name}} has received the following scholarships:\r\n\r\n{{ scholarships }}{% endif %}\r\n\r\n{{title}} {{last_name}} is making satisfactory progress." }, ] for data in templates: t = LetterTemplate(**data) t.save() p = GradProgram(unit=cmpt, label='MSc Course', description='MSc Course option') p.save() p = GradProgram(unit=cmpt, label='MSc Proj', description='MSc Project option') p.save() p = GradProgram(unit=cmpt, label='MSc Thesis', description='MSc Thesis option') p.save() p = GradProgram(unit=cmpt, label='PhD', description='Doctor of Philosophy') p.save() p = GradProgram(unit=cmpt, label='Qualifying', description='Qualifying student') p.save() p = GradProgram(unit=cmpt, label='Special', description='Special Arrangements') p.save() gr = GradRequirement(program=p, description='Achieved Speciality') gr.save() for p in GradProgram.objects.filter(unit=cmpt): gr = GradRequirement(program=p, description='Found campus') gr.save() gf = GradFlag(unit=cmpt, label='Dual Degree Program') gf.save() gf = GradFlag(unit=cmpt, label='Co-op') gf.save() grads = list(Person.objects.filter(last_name='Grad')) programs = list(GradProgram.objects.all()) today = datetime.date.today() starts = Semester.objects.filter(start__gt=today - datetime.timedelta(1000), start__lt=today) supervisors = list( set([ m.person for m in Member.objects.filter( role='INST').select_related('person') ])) # create GradStudents (and associated data) in a vaguely realistic way for g in grads + random.sample(grads, 5): # put a few in two programs p = random.choice(programs) start = random.choice(starts) sstart = start.start if random.randint(1, 2) == 1: end = start.offset(random.randint(3, 9)) else: end = None gs = GradStudent(person=g, program=p, research_area=randname(8) + 'ology', campus=random.choice([x for x, _ in CAMPUS_CHOICES]), is_canadian=randnullbool()) gs.save() gph = GradProgramHistory(student=gs, program=p, start_semester=start) gph.save() if random.randint(1, 3) == 1: p2 = random.choice( [p2 for p2 in programs if p != p2 and p.unit == p2.unit]) gph = GradProgramHistory(student=gs, program=p2, start_semester=start.offset( random.randint(1, 4))) gph.save() s = GradStatus(student=gs, status='COMP', start=start, start_date=sstart - datetime.timedelta(days=100)) s.save() if random.randint(1, 4) == 1: s = GradStatus(student=gs, status='REJE', start=start, start_date=sstart - datetime.timedelta(days=80)) s.save() else: s = GradStatus(student=gs, status='OFFO', start=start, start_date=sstart - datetime.timedelta(days=80)) s.save() s = GradStatus(student=gs, status='ACTI', start=start, start_date=sstart) s.save() if end: if random.randint(1, 3): s = GradStatus(student=gs, status='WIDR', start=end, start_date=end.start) s.save() else: s = GradStatus(student=gs, status='GRAD', start=end, start_date=end.start) s.save() gs.update_status_fields() # give some money sch = Scholarship(student=gs, scholarship_type=random.choice(scholarship_types)) sch.amount = 2000 sch.start_semester = start sch.end_semester = start.offset(2) sch.save() of = OtherFunding(student=gs, semester=start.offset(3)) of.amount = 1300 of.description = "Money fell from the sky" of.save() # promise p = Promise(student=gs, start_semester=start, end_semester=start.offset(2), amount=10000) p.save() p = Promise(student=gs, start_semester=start.offset(3), end_semester=start.offset(5), amount=10000) p.save() # flags if random.randint(1, 3) == 1: cr = CompletedRequirement(requirement=gr, student=gs, semester=start.offset(1)) cr.save() if random.randint(1, 4) == 1: gfv = GradFlagValue(flag=gf, student=gs, value=True) gfv.save() # supervisors if random.randint(1, 3) != 1: p = random.choice(supervisors) s = Supervisor(student=gs, supervisor=p, supervisor_type='POT') s.save() if random.randint(1, 2) == 1: s = Supervisor(student=gs, supervisor=p, supervisor_type='SEN') s.save() s = Supervisor(student=gs, supervisor=random.choice(supervisors), supervisor_type='COM') s.save() return itertools.chain( roles, programs, scholarship_types, GradRequirement.objects.all(), LetterTemplate.objects.all(), GradFlag.objects.all(), GradStudent.objects.all(), GradProgramHistory.objects.all(), GradStatus.objects.all(), Scholarship.objects.all(), OtherFunding.objects.all(), Promise.objects.all(), CompletedRequirement.objects.all(), GradFlagValue.objects.all(), Supervisor.objects.all(), )