source: main/waeup.sirp/trunk/src/waeup/sirp/applicants/browser.py @ 6099

Last change on this file since 6099 was 6087, checked in by Henrik Bettermann, 14 years ago

Adding some attributes to ApplicantsContainer?. Generate title and code of containers automatically.

File size: 13.8 KB
Line 
1##
2## browser.py
3## Login : <uli@pu.smp.net>
4## Started on  Sun Jun 27 11:03:10 2010 Uli Fouquet
5## $Id$
6##
7## Copyright (C) 2010 Uli Fouquet & Henrik Bettermann
8## This program is free software; you can redistribute it and/or modify
9## it under the terms of the GNU General Public License as published by
10## the Free Software Foundation; either version 2 of the License, or
11## (at your option) any later version.
12##
13## This program is distributed in the hope that it will be useful,
14## but WITHOUT ANY WARRANTY; without even the implied warranty of
15## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16## GNU General Public License for more details.
17##
18## You should have received a copy of the GNU General Public License
19## along with this program; if not, write to the Free Software
20## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21##
22"""UI components for basic applicants and related components.
23"""
24import sys
25import grok
26
27from zope.component import getUtility
28from zope.formlib.widget import CustomWidgetFactory
29from zope.interface import Invalid
30from zope.securitypolicy.interfaces import IPrincipalRoleManager
31
32from waeup.sirp.browser import (
33    WAeUPPage, WAeUPEditFormPage, WAeUPAddFormPage,
34    WAeUPDisplayFormPage, NullValidator)
35from waeup.sirp.browser.breadcrumbs import Breadcrumb
36from waeup.sirp.browser.resources import datepicker, tabs, datatable
37from waeup.sirp.browser.viewlets import ManageActionButton, PrimaryNavTab
38from waeup.sirp.image.browser.widget import (
39    ThumbnailWidget, EncodingImageFileWidget,
40    )
41from waeup.sirp.interfaces import IWAeUPObject
42from waeup.sirp.widgets.datewidget import (
43    FriendlyDateWidget, FriendlyDateDisplayWidget)
44from waeup.sirp.widgets.restwidget import ReSTDisplayWidget
45from waeup.sirp.widgets.objectwidget import (
46    WAeUPObjectWidget, WAeUPObjectDisplayWidget)
47from waeup.sirp.widgets.multilistwidget import (
48    MultiListWidget, MultiListDisplayWidget)
49
50from waeup.sirp.applicants import ResultEntry, Applicant
51from waeup.sirp.applicants.interfaces import (
52    IApplicant, IApplicantPrincipal, IApplicantPDEEditData,
53    IApplicantsRoot, IApplicantsContainer, IApplicantsContainerProvider,
54    IApplicantsContainerAdd, application_types_vocab
55    )
56
57results_widget = CustomWidgetFactory(
58    WAeUPObjectWidget, ResultEntry)
59
60results_display_widget = CustomWidgetFactory(
61    WAeUPObjectDisplayWidget, ResultEntry)
62
63list_results_widget = CustomWidgetFactory(
64    MultiListWidget, subwidget=results_widget)
65
66list_results_display_widget = CustomWidgetFactory(
67    MultiListDisplayWidget, subwidget=results_display_widget)
68
69class ApplicantsRootPage(WAeUPPage):
70    grok.context(IApplicantsRoot)
71    grok.name('index')
72    title = 'Applicants'
73    label = 'Application Section'
74    pnav = 3
75
76    def update(self):
77        super(ApplicantsRootPage, self).update()
78        datatable.need()
79        return
80
81class ManageApplicantsRootActionButton(ManageActionButton):
82    grok.context(IApplicantsRoot)
83    grok.view(ApplicantsRootPage)
84    grok.require('waeup.manageUniversity')
85    text = 'Manage application section'
86
87class ApplicantsRootManageFormPage(WAeUPEditFormPage):
88    grok.context(IApplicantsRoot)
89    grok.name('manage')
90    grok.template('applicantsrooteditpage')
91    title = 'Applicants'
92    label = 'Manage application section'
93    pnav = 3
94    grok.require('waeup.manageUniversity')
95    taboneactions = ['Add applicants container', 'Remove selected','Cancel']
96    subunits = 'Applicants Containers'
97
98    def update(self):
99        tabs.need()
100        #warning.need()
101        return super(ApplicantsRootManageFormPage, self).update()
102
103    # ToDo: Show warning message before deletion
104    @grok.action('Remove selected')
105    def delApplicantsContainers(self, **data):
106        form = self.request.form
107        child_id = form['val_id']
108        if not isinstance(child_id, list):
109            child_id = [child_id]
110        deleted = []
111        for id in child_id:
112            try:
113                del self.context[id]
114                deleted.append(id)
115            except:
116                self.flash('Could not delete %s: %s: %s' % (
117                        id, sys.exc_info()[0], sys.exc_info()[1]))
118        if len(deleted):
119            self.flash('Successfully removed: %s' % ', '.join(deleted))
120        self.redirect(self.url(self.context, '@@manage')+'#tab-1')
121        return
122
123    @grok.action('Add applicants container', validator=NullValidator)
124    def addApplicantsContainer(self, **data):
125        self.redirect(self.url(self.context, '@@add'))
126        return
127
128    @grok.action('Cancel', validator=NullValidator)
129    def cancel(self, **data):
130        self.redirect(self.url(self.context))
131        return
132
133class ApplicantsContainerAddFormPage(WAeUPAddFormPage):
134    grok.context(IApplicantsRoot)
135    grok.require('waeup.manageUniversity')
136    grok.name('add')
137    grok.template('applicantscontaineraddformpage')
138    title = 'Applicants'
139    label = 'Add applicants container'
140    pnav = 3
141
142    form_fields = grok.AutoFields(IApplicantsContainerAdd)
143    form_fields['startdate'].custom_widget = FriendlyDateWidget('le')
144    form_fields['enddate'].custom_widget = FriendlyDateWidget('le')
145
146    def update(self):
147        datepicker.need() # Enable jQuery datepicker in date fields.
148        return super(ApplicantsContainerAddFormPage, self).update()
149
150    @grok.action('Add applicants container')
151    def addApplicantsContainer(self, **data):
152        year1 = unicode(data['year'])
153        year2 = unicode(data['year']+1)
154        code = unicode(data['prefix']) + year1
155        title = unicode(application_types_vocab.getTerm(data['prefix']).title) + u' ' + year1 + u'/' + year2       
156        if code in self.context.keys():
157            self.status = Invalid('The code chosen already exists '
158                                  'in the database')
159            return
160        # Add new applicants container...
161        provider = data['provider'][1]
162        container = provider.factory()
163        self.applyData(container, **data)
164        container.code = code
165        container.title = title
166        #import pdb; pdb.set_trace()
167        self.context[code] = container
168        self.flash('Added "%s".' % code)
169        self.redirect(self.url(self.context, u'@@manage')+'#tab-1')
170        return
171
172    @grok.action('Cancel')
173    def cancel(self, **data):
174        self.redirect(self.url(self.context))
175
176class ApplicantsRootBreadcrumb(Breadcrumb):
177    """A breadcrumb for applicantsroot.
178    """
179    grok.context(IApplicantsRoot)
180    title = u'Applicants'
181
182class ApplicantsContainerBreadcrumb(Breadcrumb):
183    """A breadcrumb for applicantscontainers.
184    """
185    grok.context(IApplicantsContainer)
186
187class ApplicantsTab(PrimaryNavTab):
188    """Faculties-tab in primary navigation.
189    """
190
191    grok.context(IWAeUPObject)
192    grok.order(3)
193    grok.require('waeup.manageUniversity')
194    grok.template('primarynavtab')
195
196    pnav = 3
197    tab_title = u'Applicants'
198
199    @property
200    def link_target(self):
201        return self.view.application_url('applicants')
202
203class ApplicantsContainerPage(WAeUPDisplayFormPage):
204    """The standard view for regular applicant containers.
205    """
206    grok.context(IApplicantsContainer)
207    grok.name('index')
208    grok.template('applicantscontainerpage')
209    pnav = 3
210
211    form_fields = grok.AutoFields(IApplicantsContainer)
212    # Use friendlier date widget...
213    form_fields['startdate'].custom_widget = FriendlyDateDisplayWidget('le')
214    form_fields['enddate'].custom_widget = FriendlyDateDisplayWidget('le')
215    form_fields['description'].custom_widget = ReSTDisplayWidget
216
217    @property
218    def title(self):
219        return "Applicants Container: %s" % self.context.title
220
221    @property
222    def label(self):
223        return self.context.title
224
225class ManageApplicantsContainerActionButton(ManageActionButton):
226    grok.context(IApplicantsContainer)
227    grok.view(ApplicantsContainerPage)
228    text = 'Manage applicants container'
229
230
231class ManageApplicantsContainer(WAeUPEditFormPage):
232    grok.context(IApplicantsContainer)
233    grok.name('manage')
234    grok.template('form_manage_applicants_container')
235    form_fields = grok.AutoFields(IApplicantsContainer)
236    # Use friendlier date widget...
237    form_fields['startdate'].custom_widget = FriendlyDateWidget('le')
238    form_fields['enddate'].custom_widget = FriendlyDateWidget('le')
239
240    @property
241    def title(self):
242        return "Applicants Container: %s" % self.context.title
243
244    @property
245    def label(self):
246        return 'Manage applicants container'
247
248    pnav = 3
249
250    def update(self):
251        datepicker.need() # Enable jQuery datepicker in date fields.
252        tabs.need()
253        datatable.need()  # Enable jQurey datatables for contents listing
254        return super(ManageApplicantsContainer, self).update()
255
256    @grok.action('Save')
257    def apply(self, **data):
258        self.applyData(self.context, **data)
259        self.flash('Data saved.')
260        return
261
262    @grok.action('Back')
263    def cancel(self, **data):
264        self.redirect(self.url(self.context))
265        return
266
267class LoginApplicant(WAeUPPage):
268    grok.context(IApplicantsContainer)
269    grok.name('login')
270    grok.require('zope.Public')
271
272    title = u'Login'
273
274    @property
275    def label(self):
276        return self.title
277
278    pnav = 3
279    prefix = u'APP'
280
281    def update(self, SUBMIT=None):
282        self.ac_series = self.request.form.get('form.ac_series', None)
283        self.ac_number = self.request.form.get('form.ac_number', None)
284        if SUBMIT is None:
285            return
286
287        if self.request.principal.id == 'zope.anybody':
288            self.flash('Entered credentials are invalid')
289            return
290
291        if not IApplicantPrincipal.providedBy(self.request.principal):
292            # Don't care if user is already authenticated as non-applicant
293            return
294
295        pin = self.request.principal.access_code
296        if pin not in self.context.keys():
297            # Create applicant record
298            applicant = Applicant()
299            applicant.access_code = pin
300            self.context[pin] = applicant
301
302        # Assign current principal the owner role on created applicant
303        # record
304        role_manager = IPrincipalRoleManager(self.context)
305        role_manager.assignRoleToPrincipal(
306            'waeup.local.ApplicationOwner', self.request.principal.id)
307        self.redirect(self.url(self.context[pin], 'edit'))
308        return
309
310class DisplayApplicant(WAeUPDisplayFormPage):
311    grok.context(IApplicant)
312    grok.name('index')
313    grok.require('waeup.viewApplication')
314    form_fields = grok.AutoFields(IApplicant).omit('locked')
315    form_fields['fst_sit_results'].custom_widget = list_results_display_widget
316    form_fields['passport'].custom_widget = ThumbnailWidget
317    form_fields['date_of_birth'].custom_widget = FriendlyDateDisplayWidget('le')
318    label = 'Applicant'
319    title = 'Applicant'
320    pnav = 3
321
322class EditApplicantStudent(WAeUPEditFormPage):
323    """An applicant-centered edit view for applicant data.
324    """
325    grok.context(IApplicant)
326    grok.name('edit')
327    grok.require('waeup.editApplication')
328    form_fields = grok.AutoFields(IApplicantPDEEditData).omit('locked')
329    form_fields['passport'].custom_widget = EncodingImageFileWidget
330    form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
331    grok.template('form_edit_pde')
332
333    def emitLockMessage(self):
334        self.flash('The requested form is locked (read-only)')
335        self.redirect(self.url(self.context))
336        return
337
338    def update(self):
339        if self.context.locked:
340            self.emitLockMessage()
341            return
342        datepicker.need() # Enable jQuery datepicker in date fields.
343        super(EditApplicantStudent, self).update()
344        return
345
346    def filteredWidgets(self):
347        for widget in self.widgets:
348            if widget.name == 'form.confirm_passport':
349                continue
350            yield widget
351
352    @property
353    def label(self):
354        # XXX: Use current/upcoming session
355        return 'Apply for Post UDE Screening Test (2009/2010)'
356    title = 'Edit Application'
357    pnav = 3
358
359    @grok.action('Save')
360    def save(self, **data):
361        if self.context.locked:
362            self.emitLockMessage()
363            return
364        self.applyData(self.context, **data)
365        self.context._p_changed = True
366        return
367
368    @grok.action('Final Submit')
369    def finalsubmit(self, **data):
370        if self.context.locked:
371            self.emitLockMessage()
372            return
373        self.applyData(self.context, **data)
374        self.context._p_changed = True
375        if not self.dataComplete():
376            self.flash('Data yet not complete.')
377            return
378        self.context.locked = True
379        return
380
381    def dataComplete(self):
382        if self.context.confirm_passport is not True:
383            return False
384        if len(self.errors) > 0:
385            return False
386        return True
387
388class EditApplicantFull(WAeUPEditFormPage):
389    """A full edit view for applicant data.
390
391    This one is meant to be used by officers only.
392    """
393    grok.context(IApplicant)
394    grok.name('edit_full')
395    grok.require('waeup.editFullApplication')
396    form_fields = grok.AutoFields(IApplicantPDEEditData).omit('locked')
397    form_fields['passport'].custom_widget = EncodingImageFileWidget
398    form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
399    grok.template('form_edit_full')
400
401    def update(self):
402        if self.context.locked:
403            self.emitLockMessage()
404            return
405        datepicker.need() # Enable jQuery datepicker in date fields.
406        super(EditApplicantFull, self).update()
407        return
408
409    def filteredWidgets(self):
410        for widget in self.widgets:
411            if widget.name == 'form.confirm_passport':
412                continue
413            yield widget
414
415    @property
416    def label(self):
417        return 'Application for %s' % self.context.access_code
418    title = 'Edit Application'
419    pnav = 3
420
421    @grok.action('Save')
422    def save(self, **data):
423        self.applyData(self.context, **data)
424        self.context._p_changed = True
425        return
Note: See TracBrowser for help on using the repository browser.