Add organization name to organization application acceptance/rejection email templates.
[Melange.git] / app / soc / views / models / org_app.py
blob920bfc3402c0a176221544677165fef5a842d414
1 #!/usr/bin/python2.5
3 # Copyright 2009 the Melange authors.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 """Views for Organization App profiles.
18 """
20 __authors__ = [
21 '"Lennard de Rijk" <ljvderijk@gmail.com>',
25 import os
27 from django import forms
28 from django.utils import simplejson
30 from soc.logic import accounts
31 from soc.logic import cleaning
32 from soc.logic import dicts
33 from soc.logic import mail_dispatcher
34 from soc.logic import models as model_logic
35 from soc.logic.models import program as program_logic
36 from soc.logic.models import org_app as org_app_logic
37 from soc.views import helper
38 from soc.views.helper import access
39 from soc.views.helper import decorators
40 from soc.views.helper import redirects
41 from soc.views.helper import responses
42 from soc.views.helper import widgets
43 from soc.views.models import group_app
44 from soc.views.models import program as program_view
47 class View(group_app.View):
48 """View methods for the Organization Application model.
49 """
51 def __init__(self, params=None):
52 """Defines the fields and methods required for the base View class
53 to provide the user with list, public, create, edit and delete views.
55 Params:
56 params: a dict with params for this View
57 """
59 rights = access.Checker(params)
60 rights['create'] = ['checkIsDeveloper']
61 rights['delete'] = ['checkIsDeveloper']
62 rights['edit'] = [('checkCanEditGroupApp',
63 [org_app_logic.logic]),
64 ('checkIsActivePeriod', ['org_signup', 'scope_path'])]
65 rights['list'] = ['checkIsDeveloper']
66 rights['list_self'] = ['checkIsUser']
67 rights['show'] = ['checkIsUser']
68 rights['review'] = ['checkIsHostForProgramInScope',
69 ('checkCanReviewGroupApp', [org_app_logic.logic])]
70 rights['review_overview'] = ['checkIsHostForProgramInScope']
71 rights['bulk_accept'] = ['checkIsHostForProgramInScope']
72 rights['bulk_reject'] = ['checkIsHostForProgramInScope']
73 rights['apply'] = ['checkIsUser',
74 ('checkCanCreateOrgApp', ['org_signup']),
75 'checkIsNotStudentForProgramInScope']
77 new_params = {}
79 new_params['rights'] = rights
80 new_params['logic'] = org_app_logic.logic
82 new_params['scope_view'] = program_view
83 new_params['scope_redirect'] = redirects.getCreateRedirect
85 new_params['sidebar_grouping'] = 'Organizations'
87 new_params['list_key_order'] = [
88 'link_id', 'scope_path', 'name', 'home_page', 'email',
89 'description', 'why_applying','pub_mailing_list','irc_channel',
90 'member_criteria', 'prior_participation', 'prior_application',
91 'license_name', 'ideas', 'dev_mailing_list', 'contrib_template',
92 'contrib_disappears', 'member_disappears', 'encourage_contribs',
93 'continued_contribs']
95 patterns = [(r'^%(url_name)s/(?P<access_type>apply)/%(scope)s$',
96 'soc.views.models.%(module_name)s.create',
97 'Create an %(name_plural)s'),
98 (r'^%(url_name)s/(?P<access_type>bulk_accept)/%(scope)s$',
99 'soc.views.models.%(module_name)s.bulk_accept',
100 'Bulk Acceptation of %(name_plural)s'),
101 (r'^%(url_name)s/(?P<access_type>bulk_reject)/%(scope)s$',
102 'soc.views.models.%(module_name)s.bulk_reject',
103 'Bulk Rejection of %(name_plural)s'),]
105 new_params['extra_django_patterns'] = patterns
106 new_params['extra_key_order'] = ['admin_agreement',
107 'agreed_to_admin_agreement']
109 new_params['extra_dynaexclude'] = ['applicant', 'backup_admin', 'status',
110 'created_on', 'last_modified_on']
112 new_params['create_dynafields'] = [
113 {'name': 'link_id',
114 'base': forms.fields.CharField,
115 'label': 'Organization Link ID',
119 new_params['create_extra_dynaproperties'] = {
120 'scope_path': forms.fields.CharField(widget=forms.HiddenInput,
121 required=True),
122 'contrib_template': forms.fields.CharField(
123 widget=helper.widgets.FullTinyMCE(
124 attrs={'rows': 25, 'cols': 100})),
125 'description': forms.fields.CharField(
126 widget=helper.widgets.FullTinyMCE(
127 attrs={'rows': 25, 'cols': 100})),
128 'admin_agreement': forms.fields.Field(required=False,
129 widget=widgets.AgreementField),
130 'agreed_to_admin_agreement': forms.fields.BooleanField(
131 initial=False, required=True),
133 'clean_description': cleaning.clean_html_content('description'),
134 'clean_contrib_template': cleaning.clean_html_content('contrib_template'),
135 'clean_ideas': cleaning.clean_url('ideas'),
136 'clean': cleaning.validate_new_group('link_id', 'scope_path',
137 model_logic.organization, org_app_logic)}
139 # get rid of the clean method
140 new_params['edit_extra_dynaproperties'] = {
141 'clean': (lambda x: x.cleaned_data)}
143 new_params['name'] = "Organization Application"
144 new_params['name_plural'] = "Organization Applications"
145 new_params['name_short'] = "Org App"
146 new_params['url_name'] = "org_app"
147 new_params['group_name'] = "Organization"
148 new_params['group_url_name'] = 'org'
150 new_params['review_template'] = 'soc/org_app/review.html'
151 # TODO use a proper template that works for each program
152 new_params['accepted_mail_template'] = 'soc/org_app/mail/accepted_gsoc2009.html'
153 new_params['rejected_mail_template'] = 'soc/org_app/mail/rejected.html'
155 params = dicts.merge(params, new_params)
157 super(View, self).__init__(params=params)
159 @ decorators.merge_params
160 def reviewOverview(self, request, access_type,
161 page_name=None, params=None, **kwargs):
162 """View that allows to see organization application review overview.
164 For Args see base.View.public().
167 params['list_template'] = 'soc/org_app/review_overview.html'
168 context = {
169 'bulk_accept_link': '/org_app/bulk_accept/%(scope_path)s' % (kwargs),
170 'bulk_reject_link': '/org_app/bulk_reject/%(scope_path)s' % (kwargs),}
172 return super(View, self).reviewOverview(request, access_type,
173 page_name=page_name, params=params, context=context, **kwargs)
175 def _editContext(self, request, context):
176 """See base.View._editContext.
179 entity = context['entity']
180 form = context['form']
182 if 'scope_path' in form.initial:
183 scope_path = form.initial['scope_path']
184 elif 'scope_path' in request.POST:
185 scope_path = request.POST['scope_path']
186 else:
187 del form.fields['admin_agreement']
188 return
190 entity = program_logic.logic.getFromKeyName(scope_path)
192 if not (entity and entity.org_admin_agreement):
193 return
195 agreement = entity.org_admin_agreement
197 content = agreement.content
198 params = {'url_name': 'document'}
200 widget = form.fields['admin_agreement'].widget
201 widget.text = content
202 widget.url = redirects.getPublicRedirect(agreement, params)
204 def _review(self, request, params, app_entity, status, **kwargs):
205 """Sends out an email if an org_app has been accepted or rejected.
207 For params see group_app.View._review().
210 if status == 'accepted' or status == 'rejected':
212 default_sender = mail_dispatcher.getDefaultMailSender()
214 if not default_sender:
215 # no default sender abort
216 return
217 else:
218 (sender_name, sender) = default_sender
220 # construct the contents of the email
221 user_entity = app_entity.applicant
222 to = accounts.denormalizeAccount(user_entity.account).email()
224 context = {'sender': sender,
225 'to': to,
226 'sender_name': sender_name,
227 'to_name': user_entity.name,
228 'program_name': app_entity.scope.name
229 'org_app_name': app_entity.name}
231 if status == 'accepted':
232 # use the accepted template and subject
233 template = params['accepted_mail_template']
234 context['subject'] = 'Congratulations!'
235 context['HTTP_host'] = 'http://%s' %(os.environ['HTTP_HOST'])
236 elif status == 'rejected':
237 # use the rejected template and subject
238 template = params['rejected_mail_template']
239 context['subject'] = 'Thank you for your application'
241 # send out the constructed email
242 mail_dispatcher.sendMailFromTemplate(template, context)
244 @decorators.merge_params
245 @decorators.check_access
246 def bulkAccept(self, request, access_type,
247 page_name=None, params=None, **kwargs):
248 """Returns a HTTP Response containing JSON information needed
249 to bulk-accept orgs.
252 program_keyname = kwargs['scope_path']
253 return self._bulkReview(request, params, 'pre-accepted', 'accepted',
254 program_keyname)
256 @decorators.merge_params
257 @decorators.check_access
258 def bulkReject(self, request, access_type,
259 page_name=None, params=None, **kwargs):
260 """Returns a HTTP Response containing JSON information needed
261 to bulk-accept orgs.
264 program_keyname = kwargs['scope_path']
265 return self._bulkReview(request, params, 'pre-rejected', 'rejected',
266 program_keyname)
268 def _bulkReview(self, request, params, from_status, to_status,
269 program_keyname):
270 """Returns a HTTP Response containing JSON information needed
271 to bulk-review organization applications.
273 Args:
274 request: Standard Django HTTP Request object
275 params: Params for this view
276 from_status: The status for the applications which should
277 be reviewed (can be a list)
278 to_status: The status to which all applications should be changed to
279 program_keyname: The keyname for the program to which
280 the application belongs
283 # get the program entity from the keyname
284 program_entity = program_logic.logic.getFromKeyName(program_keyname)
286 # get all the organization applications for the
287 # given program and from_status
288 filter = {'scope': program_entity,
289 'status': from_status}
291 org_app_entities = params['logic'].getForFields(filter=filter)
293 # convert each application into a dictionary containing only the fields
294 # given by the dict_filter
295 dict_filter = ['link_id', 'name']
296 org_apps = [dicts.filter(i.toDict(), dict_filter) for i in org_app_entities]
298 to_json = {
299 'program' : program_entity.name,
300 'nr_applications' : len(org_apps),
301 'application_type' : params['name_plural'],
302 'applications': org_apps,
303 'link' : '/%s/review/%s/(link_id)?status=%s' %(
304 params['url_name'] ,program_entity.key().name(), to_status),
307 json = simplejson.dumps(to_json)
309 # use the standard JSON template to return our response
310 context = {'json': json}
311 template = 'soc/json.html'
313 return responses.respond(request, template, context)
316 view = View()
318 admin = decorators.view(view.admin)
319 bulk_accept = decorators.view(view.bulkAccept)
320 bulk_reject = decorators.view(view.bulkReject)
321 create = decorators.view(view.create)
322 delete = decorators.view(view.delete)
323 edit = decorators.view(view.edit)
324 list = decorators.view(view.list)
325 list_self = decorators.view(view.listSelf)
326 public = decorators.view(view.public)
327 export = decorators.view(view.export)
328 review = decorators.view(view.review)
329 review_overview = decorators.view(view.reviewOverview)