def test_fall_spring_ordering(self): """Check that the order of semesters is generally correct""" self.assertLess(Semester('Spring 2009'), Semester('Fall 2009')) self.assertLess(Semester('Fall 2009'), Semester('Spring 2010')) self.assertLess(Semester('Spring 2010'), Semester('FA10')) self.assertLess(Semester('FA10'), Semester(('Fall', 2011))) self.assertLess(Semester(('Fall', 2011)), Semester('Spring 2013'))
def test_past_finished_date(self): aid = FinancialAid.objects.create(application=self.application, aid_type='test', provider='provider', semester_finished=Semester( ('Spring', 2016)), installment_frequency='yearly', installment_amount=1.00) # finished in the past (no good) issues = CustomValidationIssueSet() self.application.custom_validate(issues) found_issues = issues.search(section='finaid', field='semester_finished', code='invalid') self.assertEqual(len(found_issues), 1) first_iter = iter(found_issues) self.assertNotEqual(next(first_iter).subfield, None) # finished in the present (good) aid.semester_finished = Semester(settings.FREEMONEY_DUE_DATE) issues = CustomValidationIssueSet() self.application.custom_validate(issues) found_issues = issues.search(section='finaid', field='semester_finished', code='invalid') self.assertEqual(len(found_issues), 1) first_iter = iter(found_issues) self.assertNotEqual(next(first_iter).subfield, None)
def test_semester_initiated(self): self.attempt_valid_and_invalid_values('semester_initiated', valids=(Semester('Fall 2009'), Semester('Spring 2010')), invalids=(Semester('Fall 2010'), Semester('SP11'), None, Semester('Fall 1927')))
def test_constructors(self): """Ensure that the constructor accepts all advertised formats""" a = Semester('Spring 2017') b = Semester(('Spring', 2017)) c = Semester(datetime.datetime(2017, 2, 25)) d = Semester(a) self.assertEqual(a, b) self.assertEqual(b, c) self.assertEqual(c, d)
def current_application(self): candidate_applications = [] for application in self.application_set.iterator(): if (Semester(application.due_at) == Semester( settings.FREEMONEY_DUE_DATE)): candidate_applications.append(application) if len(candidate_applications) == 0: return None elif len(candidate_applications) == 1: return candidate_applications.pop() else: raise Application.MultipleObjectsReturned()
def test_date(self): """Check that the date constructor works""" for spring_date in [ self.spring_min, datetime.date(2017, 3, 15), self.spring_max ]: self.assertEqual('Spring 2017', str(Semester(spring_date))) for fall_date in [ self.fall_min, datetime.date(2017, 10, 15), self.fall_max ]: self.assertEqual('Fall 2017', str(Semester(fall_date)))
def custom_validate_for_application(self, application, issues): """Perform check on an application (for CustomValidationIssues)""" this_semester_awards = self.for_semester(Semester(application.due_at)) for index, selection in enumerate(application.award_set.iterator()): if selection not in this_semester_awards: issues.create(section='award', field='[records]', code='invalid') # Graduating seniors can only apply for certain awards if application.semester_graduating is None: pass elif (application.semester_graduating == Semester( application.due_at)): if selection.identifier in set([ 'giff_albright', 'joe_conway', 'ambassador', 'navy_marine', 'excellence', 'pledge', 'ean_hong' ]): issues.create(section='basicinfo', field='semester_graduating', code='prohibited') # Only AEs can apply for the Giff Albright award if application.major == '': pass elif application.major == 'Architectural Engineering': pass else: if selection.identifier == 'giff_albright': issues.create(section='basicinfo', field='major', code='prohibited') # Only E SC and E MCH can apply for the Joe Conway award if application.major == '': pass elif application.major == 'Engineering Science': pass elif application.emch_minor == True: pass else: if selection.identifier == 'joe_conway': issues.create(section='basicinfo', field='major', code='prohibited') if application.award_set.count() < 1: issues.create(section='award', code='min-length')
def test_Spring_2017(self): """Check that the "Spring 2017"-style string constructor works""" s = Semester('Spring 2017') self.assertBetween(Semester(self.spring_min), Semester(s.date), Semester(self.spring_max)) s = Semester('Fall 2017') self.assertBetween(Semester(self.fall_min), Semester(s), Semester(self.fall_max))
def test_SP16(self): """Check that the "SP17"-style string constructor works""" s = Semester('SP17') self.assertBetween(self.spring_min, s.date, self.spring_max) self.assertBetween(Semester(self.spring_min), Semester(s), Semester(self.spring_max)) s = Semester('FA17') self.assertBetween(Semester(self.fall_min), Semester(s.date), Semester(self.fall_max))
def save_changes(self): submit_type = self.request.POST.get('submit-type') if submit_type.startswith('delete-'): delete_pk = int(submit_type.replace('delete-', '')) FinancialAid.objects.get(application=self.application, pk=delete_pk).delete() else: delete_pk = None current_finaids = set(self.application.financialaid_set.iterator()) preserved_finaids = set() for individual in self.form: if individual.empty_permitted: if individual.is_entirely_blank: continue else: finaid = FinancialAid.objects.create( application=self.application) current_finaids.add(finaid) preserved_finaids.add(finaid) elif individual.cleaned_data['finaid_id'] == delete_pk: continue else: finaid = None for finaid_try in current_finaids: if finaid_try.pk == individual.cleaned_data['finaid_id']: finaid = finaid_try preserved_finaids.add(finaid) break if finaid is None: raise KeyError('invalid primary key provided') for field in FinancialAidPage._direct_copy: if field in individual.cleaned_data: setattr(finaid, field, individual.cleaned_data[field]) try: finaid.installment_amount = float( individual.cleaned_data['installment_amount']) except KeyError: finaid.installment_amount = None except ValueError: finaid.installment_amount = None when_finished = (individual.cleaned_data['semestertype_finished'], individual.cleaned_data['year_finished']) if when_finished[0] != '' and when_finished[1] is not None: finaid.semester_finished = Semester(when_finished) finaid.full_clean() finaid.save() for removed_finaid in current_finaids - preserved_finaids: removed_finaid.delete()
def save_changes(self): for field in BasicInfoPage._direct_copy: setattr(self.application, field, self.form.cleaned_data[field]) self.application.psu_email = re.sub(r'^([^@]+)$', r'\[email protected]', self.form.cleaned_data['psu_email']) if self.form.cleaned_data['semester_gpa'] == '': self.application.semester_gpa = None else: try: self.application.semester_gpa = float( self.form.cleaned_data['semester_gpa'] ) except ValueError: self.application.semester_gpa = None if self.form.cleaned_data['cumulative_gpa'] == '': self.application.cumulative_gpa = None else: try: self.application.cumulative_gpa = float( self.form.cleaned_data['cumulative_gpa'] ) except ValueError: self.application.cumulative_gpa = None when_initiated = (self.form.cleaned_data['semestertype_initiated'], self.form.cleaned_data['year_initiated']) when_graduating = (self.form.cleaned_data['semestertype_graduating'], self.form.cleaned_data['year_graduating']) if when_initiated[0] != '' and when_initiated[1] is not None: self.application.semester_initiated = Semester(when_initiated) if when_graduating[0] != '' and when_graduating[1] is not None: self.application.semester_graduating = Semester(when_graduating) self.application.full_clean() self.application.save()
def for_semester(self, semester=None): """Return the ordered list of Awards for a semester. The year is ignored. It is assumed that the caller is looking for the list of awards for the current Spring or Fall semester, and not historical data or a forecast regarding past or future semesters. By default, use the semester for FREEMONEY_DUE_DATE (in settings). """ if semester == None: semester = Semester(settings.FREEMONEY_DUE_DATE) year = semester.date.year if semester == Semester(('Spring', year)): slugs = [ 'ean_hong', 'ambassador', 'giff_albright', 'joe_conway', 'daniel_summers', 'navy_marine', 'excellence', 'pledge' ] elif semester == Semester(('Fall', year)): slugs = ['ean_hong', 'excellence', 'pledge'] return [self.latest_version_of(slug) for slug in slugs]
def test_endowment_senior_limitation(self): """Ensure that a graduating senior cannot select endowment awards""" excellence = Award.objects.latest_version_of('excellence') self.application.semester_graduating = Semester('FA16') self.application.award_set.add(excellence) issues = CustomValidationIssueSet() self.application.custom_validate(issues) self.assertNotEqual( list( issues.search(section='basicinfo', field='semester_graduating', code='prohibited')), [])
def prepopulate_form(self): initial_data = [] selected_awards = self.application.award_set.all() due_semester = Semester(self.application.due_at) for award in Award.objects.for_semester(due_semester): new_data = { 'award_id': award.pk, 'name': award.name, 'description': award.description } if award in selected_awards: new_data['selected'] = True else: new_data['selected'] = False initial_data.append(new_data) return AwardSelectionFormSet(initial=initial_data)
def custom_validate(self, issues): """This is "custom" validation as per Application.custom_validate""" if self.aid_type == '': issues.create(section='finaid', field='aid_type', subfield=self.pk, code='required') if self.provider == '': issues.create(section='finaid', field='provider', subfield=self.pk, code='required') if self.installment_frequency == '': issues.create(section='finaid', field='installment_frequency', subfield=self.pk, code='required') if self.installment_amount is None: issues.create(section='finaid', field='installment_amount', subfield=self.pk, code='required') elif (self.installment_amount < 0.0 or self.installment_amount > 200000.0): issues.create(section='finaid', field='installment_amount', subfield=self.pk, code='invalid') if self.semester_finished is not None: if self.semester_finished < Semester(settings.FREEMONEY_DUE_DATE): issues.create(section='finaid', field='semester_finished', subfield=self.pk, code='invalid')
def test_differing_semester_awards(self): fall_awards = Award.objects.for_semester(Semester('FA10')) spring_awards = Award.objects.for_semester(Semester('SP17')) self.assertNotEqual(set(fall_awards), set(spring_awards))
def for_application(self, application): """Return the full collection of EssayPrompts for a particular app.""" # TODO: probably should handle a possible KeyError/AttributeError # for now, just assume that the app isn't ready if this isn't ready if application.semester_initiated is None: return [] initiated = application.semester_initiated initiated = datetime(year=initiated.date.year, month=initiated.date.month, day=initiated.date.day, tzinfo=timezone.utc) present = Semester(application.due_at) present = datetime(year=present.date.year, month=present.date.month, day=present.date.day, tzinfo=timezone.utc) diff = present - initiated # initiated this semester (NIB) or last semester (super-NIB?) if diff < timedelta(days=8 * 30): is_new_enough = True else: is_new_enough = False essays = [] for award in application.award_set.iterator(): # TODO: implement the always-in-same-group rule as # specified in the for_award docstring; for now, it is # assumed that it is in effect for prompt_or_subset in self.for_award(award): subset = None if isinstance(prompt_or_subset, EssayPrompt): subset = [prompt_or_subset] else: subset = prompt_or_subset filtered_subset = [] detected = False for prompt in subset: for inner_prompt_or_subset in essays: inner_subset = None if isinstance(inner_prompt_or_subset, EssayPrompt): inner_subset = [inner_prompt_or_subset] else: inner_subset = inner_prompt_or_subset for inner_prompt in inner_subset: if inner_prompt == prompt: detected = True break if detected: continue if (is_new_enough and prompt.identifier.startswith('newmember')): filtered_subset.append(prompt) elif (not is_new_enough and prompt.identifier.startswith('established')): filtered_subset.append(prompt) elif (not prompt.identifier.startswith('newmember') and not prompt.identifier.startswith('established')): filtered_subset.append(prompt) if len(filtered_subset) == 1: essays.append(filtered_subset[0]) elif len(filtered_subset) > 1: essays.append(filtered_subset) return essays
def _custom_validate_fields(self, issues): """Custom validation rules for fields within Application""" common_section = 'basicinfo' if self.address is None or self.address == '': issues.create(section=common_section, field='address', code='required') if self.phone is None or self.phone == '': issues.create(section=common_section, field='phone', code='required') elif not phonenumber.to_python(self.phone).is_valid(): issues.create(section=common_section, field='phone', code='invalid') if self.psu_email is None or self.psu_email == '': issues.create(section=common_section, field='psu_email', code='required') else: try: EmailValidator()(self.psu_email) if not self.psu_email.endswith('@psu.edu'): issues.create(section=common_section, field='psu_email', code='prohibited') except ValidationError: issues.create(section=common_section, field='psu_email', code='invalid') if self.preferred_email == '': # preferred_email is assumed to be psu_email if blank pass else: try: EmailValidator()(self.preferred_email) except ValidationError: issues.create(section=common_section, field='preferred_email', code='invalid') if self.psu_id is None or self.psu_id == '': issues.create(section=common_section, field='psu_id', code='required') elif not re.match(r'^9\d{8}$', self.psu_id): issues.create(section=common_section, field='psu_id', code='invalid') if self.major is None or self.major == '': issues.create(section=common_section, field='major', code='required') if self.semester_initiated is None: issues.create(section=common_section, field='semester_initiated', code='required') elif self.semester_initiated > Semester(self.due_at.date()): issues.create(section=common_section, field='semester_initiated', code='invalid') elif self.semester_initiated < Semester(('Spring', 1928)): issues.create(section=common_section, field='semester_initiated', code='invalid') if self.semester_graduating is None: issues.create(section=common_section, field='semester_graduating', code='required') elif self.semester_graduating < Semester(self.due_at.date()): issues.create(section=common_section, field='semester_graduating', code='invalid') elif self.semester_graduating > Semester(('Fall', 2099)): issues.create(section=common_section, field='semester_graduating', code='invalid') if self.cumulative_gpa == None: issues.create(section=common_section, field='cumulative_gpa', code='required') elif (self.cumulative_gpa < 0.0 or self.cumulative_gpa > 4.0): issues.create(section=common_section, field='cumulative_gpa', code='invalid') if self.semester_gpa == None: issues.create(section=common_section, field='semester_gpa', code='required') elif (self.semester_gpa < 0.0 or self.semester_gpa > 4.0): issues.create(section=common_section, field='semester_gpa', code='invalid')
def test_summer_date(self): """Check that an invalid date (e.g., during Summer 2017) fails""" with self.assertRaises(ValueError): Semester(datetime.date(2017, 6, 30))
def test_semester_graduating(self): self.attempt_valid_and_invalid_values( 'semester_graduating', valids=(Semester('Fall 2010'), Semester('Spring 2010')), invalids=(Semester('Fall 2009'), Semester('Spring 2009'), None, Semester('Spring 2100')))
def test_Spring_2017(self): """Check that the ("spring", 2017) tuple constructor works""" s = Semester(('Spring', 2017)) self.assertBetween(self.spring_min, s.date, self.spring_max) s = Semester(('fa', 2017)) self.assertBetween(Semester(self.fall_min), s, Semester(self.fall_max))