| # Copyright 2014 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. |
| |
| """This module contains the proposal related models.""" |
| |
| from google.appengine.ext import ndb |
| from google.appengine.ext.ndb import msgprop |
| |
| from melange.appengine import db as melange_db |
| |
| from protorpc import messages |
| |
| |
| class Visibility(messages.Enum): |
| """Class that enumerates possible visibility types for proposals.""" |
| #: Content of the proposal is visible to everyone. |
| PUBLIC = 1 |
| |
| #: Content of the proposal is visible to members of the organization |
| #: to which the proposal has been submitted. |
| ORG_MEMBER = 2 |
| |
| #: Content of the proposal is visible to all registered students of the |
| #: current program. |
| STUDENT = 3 |
| |
| |
| class Status(messages.Enum): |
| """Class that enumerates possible statuses of proposals.""" |
| #: The proposal has been submitted to the program. |
| PENDING = 1 |
| |
| #: The proposal has been accepted into the program and has been turned |
| #: into a student project. |
| ACCEPTED = 2 |
| |
| #: This proposal has been rejected. |
| REJECTED = 3 |
| |
| # TODO(daniel): this status should be removed. |
| #: The proposal has been ignored by the organization. |
| #: Please DO NOT USE. |
| IGNORED = 4 |
| |
| #: The proposal has been withdrawn by the student. |
| WITHDRAWN = 5 |
| |
| |
| class Score(ndb.Model): |
| """Model to store information on a single score for the proposal.""" |
| |
| #: Required field storing a reference to the profile who is an author |
| #: if the score. |
| author = ndb.KeyProperty(required=True) |
| |
| #: Required field storing numeric value associated with the score, i.e. |
| #: number of points given to the proposal. |
| value = ndb.IntegerProperty(required=True) |
| |
| |
| class Proposal(ndb.Model): |
| """Model that represents a proposal that is submitted to an organization |
| by a student participating in the program. |
| |
| Parent: |
| melange.models.profile.Profile (of the student who owns the proposal) |
| """ |
| |
| #: Required field indicating the title of the proposal. |
| title = ndb.StringProperty(required=True) |
| |
| #: Required field storing a short description of the proposal. |
| abstract = ndb.TextProperty(required=True) |
| |
| #: Required field storing actual content of the proposal. |
| content = ndb.TextProperty(required=True) |
| |
| #: Optional field storing URL linking to additional resources |
| #: associated with the proposal. |
| additional_info = ndb.StringProperty(validator=melange_db.link_validator) |
| |
| #: Required field determining who is eligible to see the proposal. |
| visibility = msgprop.EnumProperty( |
| Visibility, required=True, default=Visibility.ORG_MEMBER) |
| |
| #: List of mentors associated with the proposal. They will be assigned as |
| #: mentors if the proposal is turned into a project. |
| mentors = ndb.KeyProperty(repeated=True) |
| |
| #: Field determining whether the proposal has currently at least one |
| #: mentor assigned. |
| has_mentor = ndb.ComputedProperty(lambda self: bool(self.mentors)) |
| |
| #: List of organization members who are possible mentors for the proposal. |
| possible_mentors = ndb.KeyProperty(repeated=True) |
| |
| #: List of scores that have been given to the proposal. |
| scores = ndb.StructuredProperty(Score, repeated=True) |
| |
| #: Sum of all scores for this proposal |
| total_score = ndb.ComputedProperty( |
| lambda self: sum(score.value for score in self.scores)) |
| |
| #: Field telling whether the student is eligible to edit the proposal |
| #: after the proposal submission deadline. |
| is_editable_post_deadline = ndb.BooleanProperty(default=False) |
| |
| #: Field telling whether the proposal should be accepted and turned |
| #: into a student project. |
| accept_as_project = ndb.BooleanProperty(default=False) |
| |
| #: Field storing status of the proposal. |
| status = msgprop.EnumProperty(Status, required=True, default=Status.PENDING) |
| |
| #: Field telling whether the proposal has been ignored by the organization. |
| is_ignored = ndb.BooleanProperty(default=False) |
| |
| #: Field storing the organization to which the proposal has been submitted. |
| organization = ndb.KeyProperty(required=True) |
| |
| #: Field storing the program for which the proposal has been submitted. |
| program = ndb.KeyProperty(required=True) |
| |
| #: Field storing the date when the proposal was initially created. |
| created_on = ndb.DateTimeProperty(required=True, auto_now_add=True) |
| |
| #: Field storing the date when the proposal was modified for the last time. |
| modified_on = ndb.DateTimeProperty(required=True, auto_now=True) |
| |
| #: Values for additional fields (defined by the organization) for |
| #: this proposal. |
| extra_data = ndb.JsonProperty() |
| |
| @property |
| def count_scores(self): |
| """Returns number of scores for this proposal.""" |
| return len(self.scores) |
| |
| @property |
| def average_score(self): |
| """Returns average score for this proposal. If no scores are currently |
| defined, None is returned |
| """ |
| if not self.scores: |
| return None |
| else: |
| return float(self.total_score) / float(len(self.scores)) |