Added minimum age property to Program model.
This will allow hosts to specify a minium age requirement for Students wanting to participate in a program.
Reviewed and edited by: Lennard de Rijk
--- a/app/soc/logic/cleaning.py Sun Aug 02 23:51:55 2009 +0200
+++ b/app/soc/logic/cleaning.py Mon Aug 03 15:17:21 2009 +0200
@@ -18,6 +18,7 @@
"""
__authors__ = [
+ '"Madhusudan.C.S" <madhusudancs@gmail.com>',
'"Todd Larsen" <tlarsen@google.com>',
'"Sverre Rabbelier" <sverre@rabbelier.nl>',
'"Lennard de Rijk" <ljvderijk@gmail.com>',
@@ -53,6 +54,10 @@
DEF_NO_SUCH_DOCUMENT_MSG = ugettext(
"There is no such document with that link ID under this entity.")
+DEF_MUST_BE_ABOVE_AGE_LIMIT_FMT = ugettext(
+ "To sign up as a student for this program, you "
+ "must be at least %d years of age, as of %s.")
+
DEF_MUST_BE_ABOVE_LIMIT_FMT = ugettext(
"Must be at least %d characters, it has %d characters.")
@@ -556,6 +561,7 @@
return cleaned_data
return wrapper
+
def validate_student_proposal(org_field, scope_field,
student_logic, org_logic):
"""Validates the form of a student proposal.
@@ -600,6 +606,7 @@
return cleaned_data
return wrapper
+
def validate_student_project(org_field, mentor_field, student_field):
"""Validates the form of a student proposal.
@@ -665,6 +672,58 @@
return wrapper
+
+def validate_student_age(birth_date_field, scope_field,
+ program_logic):
+ """Checks if the student has eligibility to sign up, given
+ by his birth_date given in field_name.
+
+ Args:
+ birth_date_field: Field containing birth_date of student
+ scope_field: Field containing scope_path of the student entity
+ program_logic: Logic instance of the program
+
+ Raises ValidationError if:
+ -The student's age is less than the minimum age required by the program
+ """
+
+ def wrapper(self):
+ """Wrapper method.
+ """
+
+ cleaned_data = self.cleaned_data
+
+ birth_date = cleaned_data.get(birth_date_field)
+ program_key_name = cleaned_data.get(scope_field)
+
+ if not birth_date or not program_key_name:
+ # nothing to check, field validator will find these errors
+ return cleaned_data
+
+ # get the current program entity or bail out 404
+ entity = program_logic.getFromKeyName(program_key_name)
+
+ if not entity:
+ raise forms.ValidationError(
+ ugettext("No valid program found"))
+
+ if entity.student_min_age and entity.student_min_age_as_of:
+ # only check if both the min_age and min_age_as_of are defined
+ min_year = entity.student_min_age_as_of.year - entity.student_min_age
+ min_date = entity.student_min_age_as_of.replace(year=min_year)
+
+ if birth_date > min_date:
+ # this Student is not old enough
+ self._errors[birth_date_field] = ErrorList(
+ [DEF_MUST_BE_ABOVE_AGE_LIMIT_FMT %(
+ entity.student_min_age,
+ entity.student_min_age_as_of.strftime('%A, %B %d, %Y'))])
+ del cleaned_data[birth_date_field]
+
+ return cleaned_data
+ return wrapper
+
+
def validate_document_acl(view, creating=False):
"""Validates that the document ACL settings are correct.
"""
@@ -722,6 +781,7 @@
return rights.hasMembership(roles, django_args)
+
def validate_access(self, view, rights, prefix, scope_path, field):
"""Validates that the user has access to the ACL for the specified fields.
"""
--- a/app/soc/models/program.py Sun Aug 02 23:51:55 2009 +0200
+++ b/app/soc/models/program.py Mon Aug 03 15:17:21 2009 +0200
@@ -111,6 +111,25 @@
slots_allocation = db.TextProperty(required=False,
verbose_name=ugettext('the allocation of slots'))
+ #: Property that contains the minimum age of a student allowed to
+ #: participate
+ student_min_age = db.IntegerProperty(
+ required=False, verbose_name=ugettext('Student minimum age'))
+ student_min_age.group = ugettext('Contest Rules')
+ student_min_age.help_text = ugettext(
+ 'Minimum age of the student to sign-up in years.')
+
+ #: Property that contains the date as of which above student
+ #: minimum age requirement holds. This is a DateTimeProperty because
+ #: programs might run in a different timezone then the Appengine Server
+ #: is running on.
+ student_min_age_as_of = db.DateProperty(
+ required=False, verbose_name=ugettext('Minimum age as of'))
+ student_min_age_as_of.group = ugettext('Contest Rules')
+ student_min_age_as_of.help_text = ugettext(
+ 'Date as of which the student minimum age requirement '
+ 'should be reached.')
+
#: Required field storing the type of workflow this program has
workflow = db.StringProperty(required=True,
choices=['gsoc', 'ghop'],
--- a/app/soc/modules/ghop/models/program.py Sun Aug 02 23:51:55 2009 +0200
+++ b/app/soc/modules/ghop/models/program.py Mon Aug 03 15:17:21 2009 +0200
@@ -33,24 +33,6 @@
"""GHOP Program model extends the basic Program model.
"""
- #: Property that contains the minimum age of a student allowed to
- #: participate
- student_min_age = db.IntegerProperty(
- required=True, verbose_name=ugettext('Student minimum age'))
- student_min_age.group = ugettext('Contest Rules')
- student_min_age.help_text = ugettext(
- 'Minimum age of the student to sign-up in years.')
-
- #: Property that contains the date as of which above student
- #: minimum age requirement holds. This is a DateTimeProperty because
- #: programs might run in a different timezone then the Appengine Server
- #: is running on.
- student_min_age_as_of = db.DateTimeProperty(
- required=True, verbose_name=ugettext('Minimum age as of'))
- student_min_age_as_of.group = ugettext('Contest Rules')
- student_min_age_as_of.help_text = ugettext(
- 'Date as of which the student minimum age requirement holds.')
-
#: Required property containing the number of Tasks Students can work
#: on simultaneously. For GHOP it is 1
nr_simultaneous_tasks = db.IntegerProperty(
--- a/app/soc/views/models/student.py Sun Aug 02 23:51:55 2009 +0200
+++ b/app/soc/views/models/student.py Mon Aug 03 15:17:21 2009 +0200
@@ -144,7 +144,9 @@
updated_fields = {
'link_id': forms.CharField(widget=forms.HiddenInput,
required=True),
- 'clean_link_id': cleaning.clean_user_is_current('link_id')
+ 'clean_link_id': cleaning.clean_user_is_current('link_id'),
+ 'clean': cleaning.validate_student_age(
+ 'birth_date', 'scope_path', self._logic.getScopeLogic().logic),
}
user_create_form = dynaform.extendDynaForm(