def canResign(self, entity): """Checks if the Mentor is able to resign. Checks if there are no Student Proposals or Student Projects that have this mentor assigned to it. Args: entity: a Mentor entity """ from soc.modules.gsoc.logic.models.student_project import logic as \ student_project_logic from soc.modules.gsoc.logic.models.student_proposal import logic as \ student_proposal_logic fields = {'mentor': entity} student_project_entity = student_project_logic.getForFields( fields, unique=True) if student_project_entity: return DEF_ALREADY_MENTORING_PROJECT_MSG student_proposal_entity = student_proposal_logic.getForFields( fields, unique=True) if student_proposal_entity: return DEF_ALREADY_MENTORING_PROPOSAL_MSG return super(Logic, self).canResign(entity)
def canResign(self, entity): """Checks if the Mentor is able to resign. Checks if there are no Student Proposals or Student Projects that have this mentor assigned to it. Args: entity: a Mentor entity """ from soc.modules.gsoc.logic.models.student_project import logic as \ student_project_logic from soc.modules.gsoc.logic.models.student_proposal import logic as \ student_proposal_logic fields = {'mentor': entity} student_project_entity = student_project_logic.getForFields(fields, unique=True) if student_project_entity: return DEF_ALREADY_MENTORING_PROJECT_MSG student_proposal_entity = student_proposal_logic.getForFields(fields, unique=True) if student_proposal_entity: return DEF_ALREADY_MENTORING_PROPOSAL_MSG return super(Logic, self).canResign(entity)
def countProposals(org): filter = { 'org': org.key(), } proposals = proposal_logic.getForFields(filter=filter) mentors = [p.mentor for p in proposals if p.mentor] return len(proposals), len(mentors)
def sendStudentProposalMail(job_entity): """Job that will send out an email to a student that sent in a proposal that either got accepted or rejected. Args: job_entity: a Job entity with key_data set to [student_key] """ from soc.cron.job import FatalJobError student_keyname = job_entity.key_data[0].name() student_entity = student_logic.getFromKeyName(student_keyname) if not student_entity: raise FatalJobError('The student with keyname %s does not exist!' % (student_keyname)) # only students who have sent in a proposal will be mailed fields = {'scope': student_entity} proposal = proposal_logic.getForFields(fields, unique=True) if proposal: # a proposal has been found we must sent out an email default_sender = mail_dispatcher.getDefaultMailSender() if not default_sender: # no default sender abort raise FatalJobError( 'No valid sender address could be found, try ' 'setting a no-reply address on the site settings ' 'page') else: (sender_name, sender) = default_sender # construct the contents of the email # pylint: disable-msg=E1103 student_entity = proposal.scope program_entity = proposal.program context = { 'to': student_entity.email, 'to_name': student_entity.given_name, 'sender': sender, 'sender_name': sender_name, 'program_name': program_entity.name, } # check if the student has an accepted proposal fields['status'] = 'accepted' accepted_proposal = proposal_logic.getForFields(fields, unique=True) if accepted_proposal: # use the accepted template and subject template = DEF_ACCEPTED_MAIL_TEMPLATE context['subject'] = 'Congratulations!' context['proposal_title'] = accepted_proposal.title context['org_name'] = accepted_proposal.org.name else: # use the rejected template and subject template = DEF_REJECTED_MAIL_TEMPLATE context['subject'] = 'Thank you for applying to %s' % ( program_entity.name) # send out the constructed email mail_dispatcher.sendMailFromTemplate(template, context) # we are done here return
class View(organization.View): """View methods for the Organization model. """ def __init__(self, params=None): """Defines the fields and methods required for the base View class to provide the user with list, public, create, edit and delete views. Params: params: a dict with params for this View """ rights = access.GSoCChecker(params) rights['any_access'] = ['allow'] rights['show'] = ['allow'] rights['create'] = ['checkIsDeveloper'] rights['edit'] = [('checkHasRoleForKeyFieldsAsScope', org_admin_logic), ('checkGroupIsActiveForLinkId', org_logic)] rights['delete'] = ['checkIsDeveloper'] rights['home'] = ['allow'] rights['public_list'] = ['allow'] rights['applicant'] = [('checkIsOrgAppAccepted', org_app_logic)] rights['apply_mentor'] = ['checkIsUser'] rights['list_requests'] = [('checkHasRoleForKeyFieldsAsScope', org_admin_logic)] rights['list_roles'] = [('checkHasRoleForKeyFieldsAsScope', org_admin_logic)] rights['list_proposals'] = [ ('checkHasAny', [[('checkHasRoleForKeyFieldsAsScope', [org_admin_logic, ['active', 'inactive']]), ('checkHasRoleForKeyFieldsAsScope', [mentor_logic, ['active', 'inactive']])]]) ] new_params = {} new_params['logic'] = org_logic new_params['rights'] = rights new_params['scope_view'] = program_view new_params['name'] = "GSoC Organization" new_params['module_name'] = "organization" new_params['sidebar_grouping'] = 'Organizations' new_params['module_package'] = 'soc.modules.gsoc.views.models' new_params['url_name'] = 'gsoc/org' new_params['document_prefix'] = 'gsoc_org' new_params['mentor_role_name'] = 'gsoc_mentor' new_params['mentor_url_name'] = 'gsoc/mentor' new_params['org_admin_role_name'] = 'gsoc_org_admin' patterns = [] patterns += [ (r'^org_tags/(?P<access_type>pick)$', '%(module_package)s.%(module_name)s.pick_suggested_tags', "Pick a list of suggested tags."), ] new_params['extra_django_patterns'] = patterns new_params['extra_dynaexclude'] = [ 'slots', 'slots_calculated', 'nr_applications', 'nr_mentors' ] new_params['create_extra_dynaproperties'] = { 'tags': widgets.ReferenceField( required=False, reference_url='org_tags', label=ugettext('Tags'), help_text=ugettext("A list of comma seperated tags"), example_text="e.g. python, django, appengine", filter=['scope_path'], group="1. Public Info"), 'clean_tags': gsoc_cleaning.cleanTagsList('tags', gsoc_cleaning.COMMA_SEPARATOR), 'contrib_template': forms.fields.CharField(widget=helper.widgets.FullTinyMCE( attrs={ 'rows': 25, 'cols': 100 })), 'clean_contrib_template': cleaning.clean_html_content('contrib_template'), 'clean_facebook': cleaning.clean_url('facebook'), 'clean_twitter': cleaning.clean_url('twitter'), 'clean_blog': cleaning.clean_url('blog'), } new_params['org_app_logic'] = org_app_logic params = dicts.merge(params, new_params, sub_merge=True) super(View, self).__init__(params) self._params['public_field_keys'].append('tags') self._params['public_field_names'].append("Tags") self._params['public_field_extra'] = lambda entity: { 'ideas': lists.urlize(entity.ideas, 'Click Here'), 'tags': entity.tags_string(entity.org_tag), } self._params['select_field_extra'] = self._params['public_field_extra'] def _editGet(self, request, entity, form): """See base.View._editGet(). """ if entity.org_tag: form.fields['tags'].initial = entity.tags_string(entity.org_tag) return super(View, self)._editGet(request, entity, form) def _editPost(self, request, entity, fields): """See base.View._editPost(). """ super(View, self)._editPost(request, entity, fields) fields['org_tag'] = { 'tags': fields['tags'], 'scope': entity.scope if entity else fields['scope'] } @decorators.check_access def pickSuggestedTags(self, request, access_type, page_name=None, params=None, **kwargs): """Returns a JSON representation of a list of organization tags that are suggested for a given GSoCProgram in scope. """ if 'scope_path' not in request.GET: data = [] else: program = program_logic.getFromKeyName( request.GET.get('scope_path')) if not program: data = [] else: fun = soc.cache.logic.cache(OrgTag.get_for_custom_query) suggested_tags = fun(OrgTag, filter={'scope': program}, order=None) # TODO: this should be refactored after the issue with autocompletion # is resolved data = simplejson.dumps({ 'data': [{ 'link_id': item['tag'] } for item in [dicts.toDict(tag, ['tag']) for tag in suggested_tags]], 'autocomplete_options': { 'multiple': True, 'selectFirst': False } }) return self.json(request, data, False) # TODO (dhans): merge common items with the GCI module in a single function def _getExtraMenuItems(self, role_description, params=None): """Used to create the specific Organization menu entries. For args see group.View._getExtraMenuItems(). """ submenus = [] group_entity = role_description['group'] program_entity = group_entity.scope roles = role_description['roles'] mentor_entity = roles.get('gsoc_mentor') admin_entity = roles.get('gsoc_org_admin') is_active_mentor = mentor_entity and mentor_entity.status == 'active' is_active_admin = admin_entity and admin_entity.status == 'active' if admin_entity or mentor_entity: # add a link to view all the student proposals submenu = (redirects.getListProposalsRedirect( group_entity, params), "Manage Student Proposals", 'any_access') submenus.append(submenu) # add a link to manage student projects after they have been announced if timeline_helper.isAfterEvent( program_entity.timeline, 'accepted_students_announced_deadline'): submenu = (redirects.getManageOverviewRedirect( group_entity, {'url_name': 'gsoc/student_project'}), "Manage Student Projects", 'any_access') submenus.append(submenu) if is_active_admin: # add a link to the management page submenu = (redirects.getListRolesRedirect(group_entity, params), "Manage Admins and Mentors", 'any_access') submenus.append(submenu) # add a link to invite an org admin submenu = (redirects.getInviteRedirectForRole( group_entity, 'gsoc/org_admin'), "Invite an Admin", 'any_access') submenus.append(submenu) # add a link to invite a member submenu = (redirects.getInviteRedirectForRole( group_entity, 'gsoc/mentor'), "Invite a Mentor", 'any_access') submenus.append(submenu) # add a link to the request page submenu = (redirects.getListRequestsRedirect(group_entity, params), "List Requests and Invites", 'any_access') submenus.append(submenu) # add a link to the edit page submenu = (redirects.getEditRedirect(group_entity, params), "Edit Organization Profile", 'any_access') submenus.append(submenu) if is_active_admin or is_active_mentor: submenu = (redirects.getCreateDocumentRedirect( group_entity, params['document_prefix']), "Create a New Document", 'any_access') submenus.append(submenu) submenu = (redirects.getListDocumentsRedirect( group_entity, params['document_prefix']), "List Documents", 'any_access') submenus.append(submenu) if is_active_admin: # add a link to the resign page submenu = (redirects.getManageRedirect( roles['gsoc_org_admin'], {'url_name': 'gsoc/org_admin'}), "Resign as Admin", 'any_access') submenus.append(submenu) # add a link to the edit page submenu = (redirects.getEditRedirect( roles['gsoc_org_admin'], {'url_name': 'gsoc/org_admin'}), "Edit My Admin Profile", 'any_access') submenus.append(submenu) if is_active_mentor: # add a link to the resign page submenu = (redirects.getManageRedirect( roles['gsoc_mentor'], {'url_name': 'gsoc/mentor'}), "Resign as Mentor", 'any_access') submenus.append(submenu) # add a link to the edit page submenu = (redirects.getEditRedirect(roles['gsoc_mentor'], {'url_name': 'gsoc/mentor'}), "Edit My Mentor Profile", 'any_access') submenus.append(submenu) return submenus def getListProposalsData(self, request, params_collection, org_entity): """Returns the list data for listProposals. Args: request: HTTPRequest object params_collection: List of list Params indexed with the idx of the list org_entity: GSoCOrganization entity for which the lists are generated """ from soc.modules.gsoc.logic.models.proposal_duplicates import logic \ as pd_logic from soc.modules.gsoc.logic.models.ranker_root import logic \ as ranker_root_logic idx = lists.getListIndex(request) # default list settings args = [] visibility = None if idx == 0: filter = {'org': org_entity, 'status': 'new'} elif idx == 1: # retrieve the ranker fields = { 'link_id': student_proposal.DEF_RANKER_NAME, 'scope': org_entity } ranker_root = ranker_root_logic.getForFields(fields, unique=True) ranker = ranker_root_logic.getRootFromEntity(ranker_root) status = {} program_entity = org_entity.scope # only when the program allows allocations # we show that proposals are likely to be # accepted or rejected if program_entity.allocations_visible: proposals = sp_logic.getProposalsToBeAcceptedForOrg(org_entity) duplicate_proposals = [] # get all the duplicate entities if duplicates can be shown # to the organizations and make a list of all such proposals. if program_entity.duplicates_visible: duplicate_properties = { 'orgs': org_entity, 'is_duplicate': True } duplicates = pd_logic.getForFields(duplicate_properties) for duplicate in duplicates: duplicate_proposals.extend(duplicate.duplicates) for proposal in proposals: proposal_key = proposal.key() if proposal.status == 'pending' and proposal_key in duplicate_proposals: status[proposal_key] = """<strong><font color="red"> Duplicate</font></strong>""" else: status[proposal_key] = """<strong><font color="green"> Pending acceptance</font><strong>""" filter = { 'org': org_entity, 'status': ['accepted', 'pending', 'rejected'] } # some extras for the list args = [ranker, status] visibility = 'review' elif idx == 2: # check if the current user is a mentor user_entity = user_logic.getCurrentUser() fields = { 'user': user_entity, 'scope': org_entity, 'status': ['active', 'inactive'] } mentor_entity = mentor_logic.getForFields(fields, unique=True) filter = { 'org': org_entity, 'mentor': mentor_entity, 'status': ['pending', 'accepted', 'rejected'] } elif idx == 3: filter = {'org': org_entity, 'status': 'invalid'} else: return lists.getErrorResponse(request, "idx not valid") params = params_collection[idx] contents = helper.lists.getListData(request, params, filter, visibility=visibility, args=args) return lists.getResponse(request, contents) @decorators.merge_params @decorators.check_access def listProposals(self, request, access_type, page_name=None, params=None, **kwargs): """Lists all proposals for the organization given in kwargs. For params see base.View.public(). """ from soc.modules.gsoc.logic.models.proposal_duplicates_status import \ logic as ds_logic try: org_entity = self._logic.getFromKeyFieldsOr404(kwargs) except out_of_band.Error, error: return helper.responses.errorResponse( error, request, template=params['error_public']) program_entity = org_entity.scope is_after_deadline = timeline_helper.isAfterEvent( program_entity.timeline, 'accepted_students_announced_deadline') if is_after_deadline: redirect_fun = redirects.getProposalCommentRedirect else: redirect_fun = redirects.getReviewRedirect context = {} context['entity'] = org_entity # whether or not the amount of slots assigned should be shown context['slots_visible'] = org_entity.scope.allocations_visible # used to check the status of the duplicate process context['duplicate_status'] = ds_logic.getOrCreateForProgram( org_entity.scope) program_entity = org_entity.scope page_name = '%s %s (%s)' % (page_name, org_entity.name, program_entity.short_name) list_params = student_proposal_view.view.getParams().copy() list_params['list_template'] = 'soc/student_proposal/list_for_org.html' np_params = list_params.copy() # new proposals description = ugettext('List of new %s sent to %s') % ( np_params['name_plural'], org_entity.name) np_params['list_description'] = description np_params['public_row_extra'] = lambda entity: { 'link': redirect_fun(entity, np_params), } rp_params = list_params.copy() # ranked proposals rp_params['review_field_keys'] = [ 'rank', 'title', 'student', 'mentor', 'score', 'status', 'last_modified_on', 'abstract', 'content', 'additional_info', 'created_on' ] rp_params['review_field_hidden'] = [ 'abstract', 'content', 'additional_info', 'created_on' ] rp_params['review_field_names'] = [ 'Rank', 'Title', 'Student', 'Mentor', 'Score', 'Status', 'Last Modified On', 'Abstract', 'Content', 'Additional Info', 'Created On' ] rp_params['review_field_no_filter'] = ['status'] rp_params['review_field_prefetch'] = ['scope', 'mentor', 'program'] rp_params['review_field_extra'] = lambda entity, ranker, status: { 'rank': ranker.FindRanks([[entity.score]])[0] + 1, 'student': entity.scope.name(), 'mentor': entity.mentor.name() if entity.mentor else '%s Proposed' % len(entity.possible_mentors), 'status': status.get(entity.key(), '<font color="red">Pending rejection</font>') if ( entity.program.allocations_visible \ and entity.status == 'pending') else entity.status, } rp_params['review_row_action'] = { "type": "redirect_custom", "parameters": dict(new_window=True), } rp_params['review_row_extra'] = lambda entity, *args: { 'link': redirect_fun(entity, rp_params) } rp_params['review_field_props'] = { "score": { "sorttype": "integer", }, "rank": { "sorttype": "integer", }, } rp_params['review_conf_min_num'] = 50 description = ugettext('%s already under review sent to %s') % ( rp_params['name_plural'], org_entity.name) rp_params['list_description'] = description mp_params = list_params.copy() # proposals mentored by current user description = ugettext('List of %s sent to %s you are mentoring') % ( mp_params['name_plural'], org_entity.name) mp_params['list_description'] = description mp_params['public_row_extra'] = lambda entity: { 'link': redirect_fun(entity, mp_params) } ip_params = list_params.copy() # invalid proposals ip_params['list_description'] = ugettext( 'List of invalid %s sent to %s ') % (ip_params['name_plural'], org_entity.name) ip_params['public_row_extra'] = lambda entity: { 'link': redirect_fun(entity, ip_params) } if lists.isDataRequest(request): # retrieving data for a list return self.getListProposalsData( request, [np_params, rp_params, mp_params, ip_params], org_entity) # fill contents for all the needed lists contents = [] # check if there are new proposals if so show them in a separate list fields = {'org': org_entity, 'status': 'new'} new_proposal = sp_logic.getForFields(fields, unique=True) if new_proposal: # we should add this list because there is a new proposal np_list = helper.lists.getListGenerator(request, np_params, idx=0) contents.append(np_list) order = ['-score'] # the list of proposals that have been reviewed should always be shown rp_list = helper.lists.getListGenerator(request, rp_params, order=order, visibility='review', idx=1) contents.append(rp_list) # check whether the current user is a mentor for the organization user_entity = user_logic.getCurrentUser() fields = { 'user': user_entity, 'scope': org_entity, 'status': ['active', 'inactive'] } mentor_entity = mentor_logic.getForFields(fields, unique=True) if mentor_entity: # show the list of all proposals that this user is mentoring mp_list = helper.lists.getListGenerator(request, mp_params, idx=2) contents.append(mp_list) # check if there are invalid proposals if so show them in a separate list fields = {'org': org_entity, 'status': 'invalid'} invalid_proposal = sp_logic.getForFields(fields, unique=True) if invalid_proposal: ip_list = helper.lists.getListGenerator(request, ip_params, idx=3) contents.append(ip_list) return self._list(request, list_params, contents, page_name, context)