def create_ra_data(): unit = Unit.objects.get(slug='cmpt') s = Semester.objects.get(name=TEST_SEMESTER) superv = list(possible_supervisor_people([unit])) empl = list(itertools.chain(Person.objects.filter(userid__endswith='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()
def select_letter(request, ra_slug, print_only=None): appointment = get_object_or_404(RAAppointment, slug=ra_slug, deleted=False, unit__in=request.units) letter_choices = RAAppointment.letter_choices(request.units) if request.method == 'POST': filled_form = LetterSelectForm(data=request.POST, choices=letter_choices) if filled_form.is_valid(): appointment.build_letter_text( filled_form.cleaned_data['letter_choice']) if print_only == 'print': return HttpResponseRedirect( reverse('ra:letter', kwargs=({ 'ra_slug': ra_slug }))) else: return HttpResponseRedirect( reverse('ra:edit_letter', kwargs=({ 'ra_slug': ra_slug }))) else: new_form = LetterSelectForm(choices=letter_choices) context = { 'form': new_form, 'ra_slug': ra_slug, 'print_only': print_only } return render(request, 'ra/select_letter.html', context)
def edit_letter(request, ra_slug): appointment = get_object_or_404(RAAppointment, slug=ra_slug, deleted=False, unit__in=request.units) if request.method == 'POST': form = RALetterForm(request.POST, instance=appointment) if form.is_valid(): form.save() messages.success( request, 'Updated RA Letter Text for ' + appointment.person.first_name + " " + appointment.person.last_name) return HttpResponseRedirect( reverse('ra:student_appointments', kwargs=({ 'userid': appointment.person.userid }))) else: if not appointment.offer_letter_text: letter_choices = RAAppointment.letter_choices(request.units) if len(letter_choices) == 1: # why make them select from one? appointment.build_letter_text(letter_choices[0][0]) else: return HttpResponseRedirect( reverse('ra:select_letter', kwargs=({ 'ra_slug': ra_slug }))) form = RALetterForm(instance=appointment) context = {'appointment': appointment, 'form': form} return render(request, 'ra/edit_letter.html', context)
def select_letter(request, ra_slug, print_only=None): appointment = get_object_or_404(RAAppointment, slug=ra_slug, deleted=False, unit__in=request.units) # Forcing sorting of the letter choices so the Standard template is first. letter_choices = sorted(RAAppointment.letter_choices(request.units)) if request.method == 'POST': filled_form = LetterSelectForm(data=request.POST, choices=letter_choices) if filled_form.is_valid(): appointment.build_letter_text(filled_form.cleaned_data['letter_choice']) if print_only == 'print': return HttpResponseRedirect(reverse('ra:letter', kwargs=({'ra_slug': ra_slug}))) else: return HttpResponseRedirect(reverse('ra:edit_letter', kwargs=({'ra_slug': ra_slug}))) else: new_form = LetterSelectForm(choices=letter_choices) context = {'form': new_form, 'ra_slug': ra_slug, 'print_only': print_only} return render(request, 'ra/select_letter.html', context)
def letter(request, ra_slug): appointment = get_object_or_404(RAAppointment, slug=ra_slug, deleted=False, unit__in=request.units) if not appointment.offer_letter_text: letter_choices = RAAppointment.letter_choices(request.units) if len(letter_choices) == 1: # why make them select from one? appointment.build_letter_text(letter_choices[0][0]) else: return HttpResponseRedirect( reverse('ra:select_letter', kwargs=({ 'ra_slug': ra_slug, 'print_only': 'print' }))) response = HttpResponse(content_type="application/pdf") response['Content-Disposition'] = 'inline; filename="%s-letter.pdf"' % ( appointment.slug) letter = OfficialLetter(response, unit=appointment.unit) contents = LetterContents( to_addr_lines=[ appointment.person.name(), 'c/o ' + appointment.unit.name ], from_name_lines=[ appointment.hiring_faculty.first_name + " " + appointment.hiring_faculty.last_name, appointment.unit.name ], closing="Yours Truly", signer=appointment.hiring_faculty, cosigner_lines=[ 'I agree to the conditions of employment', appointment.person.first_name + " " + appointment.person.last_name ]) contents.add_paragraphs([ "Dear " + appointment.person.get_title() + ' ' + appointment.person.last_name ]) contents.add_paragraphs(appointment.letter_paragraphs()) letter.add_letter(contents) letter.write() return response
def edit_letter(request, ra_slug): appointment = get_object_or_404(RAAppointment, slug=ra_slug, deleted=False, unit__in=request.units) if request.method == 'POST': form = RALetterForm(request.POST, instance=appointment) if form.is_valid(): form.save() messages.success(request, 'Updated RA Letter Text for ' + appointment.person.first_name + " " + appointment.person.last_name) return HttpResponseRedirect(reverse('ra:student_appointments', kwargs=({'userid': appointment.person.userid}))) else: if not appointment.offer_letter_text: letter_choices = RAAppointment.letter_choices(request.units) if len(letter_choices) == 1: # why make them select from one? appointment.build_letter_text(letter_choices[0][0]) else: return HttpResponseRedirect(reverse('ra:select_letter', kwargs=({'ra_slug': ra_slug}))) form = RALetterForm(instance=appointment) context = {'appointment': appointment, 'form': form} return render(request, 'ra/edit_letter.html', context)
def letter(request, ra_slug): appointment = get_object_or_404(RAAppointment, slug=ra_slug, deleted=False, unit__in=request.units) if not appointment.offer_letter_text: letter_choices = RAAppointment.letter_choices(request.units) if len(letter_choices) == 1: # why make them select from one? appointment.build_letter_text(letter_choices[0][0]) else: return HttpResponseRedirect(reverse('ra:select_letter', kwargs=({'ra_slug': ra_slug, 'print_only': 'print'}))) response = HttpResponse(content_type="application/pdf") response['Content-Disposition'] = 'inline; filename="%s-letter.pdf"' % (appointment.slug) letter = OfficialLetter(response, unit=appointment.unit) contents = LetterContents( to_addr_lines=[appointment.person.name(), 'c/o '+appointment.unit.name], from_name_lines=[appointment.hiring_faculty.first_name + " " + appointment.hiring_faculty.last_name, appointment.unit.name], closing="Yours Truly", signer=appointment.hiring_faculty, cosigner_lines=['I agree to the conditions of employment', appointment.person.first_name + " " + appointment.person.last_name]) contents.add_paragraphs(["Dear " + appointment.person.get_title() + ' ' + appointment.person.last_name]) contents.add_paragraphs(appointment.letter_paragraphs()) letter.add_letter(contents) letter.write() return response
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, expiry=role_expiry) r1.save() r2 = Role(person=d, role='FUND', unit=unit, expiry=role_expiry) 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(), )
def _build_funding_totals(semester, programs, units): """ Calculate funding in each category in this semester, for students in these units. Returns list of programs annotated with the totals """ # build mapping of Person.id to most-likely-currently-interesting GradProgram they're in gradstudents = GradStudent.objects.filter( program__unit__in=units).select_related('start_semester', 'person') gradstudents = list(gradstudents) gradstudents.sort(key=lambda gs: (-ACTIVE_STATUS_ORDER[gs.current_status], __startsem_name(gs))) student_programs = {} for gs in gradstudents: student_programs[gs.person_id] = gs.program_id del gradstudents programs = list(programs) non_grad = _FakeProgram(label="Non Grad *", pid=-1) programs.append(non_grad) total = _FakeProgram(label="Total **", pid=-2) programs.append(total) for prog in programs: prog.funding_ta = decimal.Decimal(0) prog.funding_ra = decimal.Decimal(0) prog.funding_schol = decimal.Decimal(0) prog.funding_other = decimal.Decimal(0) prog_lookup = dict((prog.id, prog) for prog in programs) # TA funding tacourses = TACourse.objects.filter(contract__posting__semester=semester, contract__posting__unit__in=units, contract__status='SGN') \ .select_related('contract__application') for crs in tacourses: person_id = crs.contract.application.person_id if person_id in student_programs: prog_id = student_programs[person_id] prog = prog_lookup[prog_id] else: prog = non_grad pay = crs.pay() prog.funding_ta += pay total.funding_ta += pay # RA funding sem_st, sem_en = RAAppointment.start_end_dates(semester) raappt = RAAppointment.objects.filter(unit__in=units, deleted=False, end_date__gte=sem_st, start_date__lte=sem_en) for ra in raappt: person_id = ra.person_id if person_id in student_programs: prog_id = student_programs[person_id] prog = prog_lookup[prog_id] else: prog = non_grad semlen = ra.semester_length() if semlen == 0: semlen = 1 pay = ra.lump_sum_pay / semlen prog.funding_ra += pay total.funding_ra += pay # scholarships schols = Scholarship.objects.filter(student__program__unit__in=units, start_semester__name__lte=semester.name, end_semester__name__gte=semester.name) \ .select_related('student', 'start_semester', 'end_semester') for sch in schols: prog_id = sch.student.program_id prog = prog_lookup[prog_id] length = sch.end_semester - sch.start_semester + 1 pay = sch.amount / length prog.funding_schol += pay total.funding_schol += pay # other funding others = OtherFunding.objects.filter( student__program__unit__in=units, semester=semester).select_related('student') for oth in others: prog_id = oth.student.program_id prog = prog_lookup[prog_id] pay = oth.amount prog.funding_other += pay total.funding_other += pay return programs
def expiring_ras_reminder(): RAAppointment.email_expiring_ras() RARequest.email_expiring_ras()
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 _build_funding_totals(semester, programs, units): """ Calculate funding in each category in this semester, for students in these units. Returns list of programs annotated with the totals """ # build mapping of Person.id to most-likely-currently-interesting GradProgram they're in gradstudents = GradStudent.objects.filter(program__unit__in=units).select_related('start_semester') # decorate so most-interesting sorts last gradstudents = [(-ACTIVE_STATUS_ORDER[gs.current_status], __startsem_name(gs), gs) for gs in gradstudents] gradstudents.sort() student_programs = {} for _,_,gs in gradstudents: student_programs[gs.person_id] = gs.program_id del gradstudents programs = list(programs) non_grad = _FakeProgram(label="Non Grad *", pid=-1) programs.append(non_grad) total = _FakeProgram(label="Total **", pid=-2) programs.append(total) for prog in programs: prog.funding_ta = decimal.Decimal(0) prog.funding_ra = decimal.Decimal(0) prog.funding_schol = decimal.Decimal(0) prog.funding_other = decimal.Decimal(0) prog_lookup = dict((prog.id, prog) for prog in programs) # TA funding tacourses = TACourse.objects.filter(contract__posting__semester=semester, contract__posting__unit__in=units, contract__status='SGN') \ .select_related('contract__application') for crs in tacourses: person_id = crs.contract.application.person_id if person_id in student_programs: prog_id = student_programs[person_id] prog = prog_lookup[prog_id] else: prog = non_grad pay = crs.pay() prog.funding_ta += pay total.funding_ta += pay # RA funding sem_st, sem_en = RAAppointment.start_end_dates(semester) raappt = RAAppointment.objects.filter(unit__in=units, deleted=False, end_date__gte=sem_st, start_date__lte=sem_en) for ra in raappt: person_id = ra.person_id if person_id in student_programs: prog_id = student_programs[person_id] prog = prog_lookup[prog_id] else: prog = non_grad semlen = ra.semester_length() if semlen == 0: semlen = 1 pay = ra.lump_sum_pay/semlen prog.funding_ra += pay total.funding_ra += pay # scholarships schols = Scholarship.objects.filter(student__program__unit__in=units, start_semester__name__lte=semester.name, end_semester__name__gte=semester.name) \ .select_related('student', 'start_semester', 'end_semester') for sch in schols: prog_id = sch.student.program_id prog = prog_lookup[prog_id] length = sch.end_semester - sch.start_semester + 1 pay = sch.amount / length prog.funding_schol += pay total.funding_schol += pay # other funding others = OtherFunding.objects.filter(student__program__unit__in=units, semester=semester).select_related('student') for oth in others: prog_id = oth.student.program_id prog = prog_lookup[prog_id] pay = oth.amount prog.funding_other += pay total.funding_other += pay return programs
def expiring_ras_reminder(): RAAppointment.email_expiring_ras()