blob: 9e4f9d66310347f32caf949ccc9b276712f30535 [file] [log] [blame]
# Copyright 2013 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Logic for surveys."""
from google.appengine.ext import ndb
from melange.utils import time
from summerofcode.models import survey as survey_model
def getPersonalExtension(profile_key, survey_key):
"""Returns personal extension for the specified survey and profile.
Args:
profile_key: profile key.
survey_key: survey key.
Returns:
survey_model.PersonalExtension if an entity for the specified parameters
exists, None otherwise.
"""
# TODO(daniel): NDB migration
ndb_survey_key = ndb.Key.from_old_key(survey_key)
query = survey_model.PersonalExtension.query(
survey_model.PersonalExtension.survey == ndb_survey_key,
ancestor=profile_key)
return query.get()
def getSurveyActivePeriod(survey, extension=None):
"""Returns period during which the specified survey is active.
If no extension is specified, the period is simply defined by start and
end dates of the specified survey.
Otherwise, it is checked if the extension actually extends this period
in any direction. Specifically, if its start date comes before the survey
start date, the period of activeness starts when the extension starts.
Similarly, if the extension ends after the survey normally ends, the period
of activeness is extended to that point.
Args:
survey: survey entity
extension: optional extension for the survey
Returns:
Period object describing when the specified survey is active.
"""
if not extension:
period_start = survey.survey_start
period_end = survey.survey_end
else:
if not extension.start_date:
period_start = survey.survey_start
else:
period_start = min(survey.survey_start, extension.start_date)
if not extension.end_date:
period_end = survey.survey_end
else:
period_end = max(survey.survey_end, extension.end_date)
return time.Period(start=period_start, end=period_end)
def _isSurveyInPeriodStates(survey, profile_key, period_states):
"""Tells whether the specified survey is currently in one of the specified
period states for the specified profile.
Args:
survey: survey entity.
profile_key: profile key for which the survey state is checked.
period_states: list of allowed PERIOD_STATES.
Returns:
True, if the survey is currently in one of the specified period states.
False, otherwise.
"""
active_period = getSurveyActivePeriod(survey)
if active_period.state in period_states:
return True
else:
# try finding a personal extension for the student
extension = getPersonalExtension(profile_key, survey.key())
active_period = getSurveyActivePeriod(survey, extension=extension)
return active_period.state in period_states
def isSurveyActive(survey, profile_key):
"""Tells whether the specified survey is currently active for the specified
profile or not.
Args:
survey: survey entity.
profile_key: profile key for which the survey state is checked.
Returns:
True, if the survey is currently active. False, otherwise.
"""
return _isSurveyInPeriodStates(survey, profile_key, [time.IN_PERIOD_STATE])
def hasSurveyStarted(survey, profile_key):
"""Tells whether the specified survey has already started for the specified
profile or not.
Please not that the function returns True even if the survey is not
active anymore.
Args:
survey: survey entity.
profile_key: profile key for which the survey state is checked.
Returns:
True, if the survey has already started. False, otherwise.
"""
return _isSurveyInPeriodStates(
survey, profile_key, [time.IN_PERIOD_STATE, time.POST_PERIOD_STATE])
def createOrUpdatePersonalExtension(profile_key, survey_key, **kwargs):
"""Creates personal extension for the specified survey and profile.
In order to make sure that there is at most one personal extension between
a particular profile and a survey, this function should be run within
a transaction.
The result of this function is saved in the datastore.
Args:
profile_key: profile_key.
survey_key: survey key.
Returns:
newly created or updated personal extension entity.
"""
extension = getPersonalExtension(profile_key, survey_key)
if extension:
extension.populate(**kwargs)
else:
# TODO(daniel): NDB migration; key does not need to be translated
# when Profile and Survey models migrate to NDB
ndb_survey_key = ndb.Key.from_old_key(survey_key)
extension = survey_model.PersonalExtension(
parent=profile_key, survey=ndb_survey_key, **kwargs)
extension.put()
return extension