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

Last change on this file since 6082 was 6082, checked in by uli, 14 years ago

Reorder imports, fixes.

File size: 13.6 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 ReSTWidget
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
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 = FriendlyDateDisplayWidget('le')
144    form_fields['enddate'].custom_widget = FriendlyDateDisplayWidget('le')
145    form_fields['description'].custom_widget = ReSTWidget
146
147    @grok.action('Add applicants container')
148    def addApplicantsContainer(self, **data):
149        if data['code'] in self.context.keys():
150            self.status = Invalid('The name chosen already exists '
151                                  'in the database')
152            return
153        # Add new applicants container...
154        provider = getUtility(IApplicantsContainerProvider,
155                              name=getattr(data['provider'],
156                                   'grokcore.component.directive.name'))
157        container = provider.factory()
158        self.applyData(container, **data)
159        self.context[data['code']] = container
160        self.flash('Added "%s".' % data['code'])
161        self.redirect(self.url(self.context, u'@@manage')+'#tab-1')
162        return
163
164    @grok.action('Cancel')
165    def cancel(self, **data):
166        self.redirect(self.url(self.context))
167
168class ApplicantsRootBreadcrumb(Breadcrumb):
169    """A breadcrumb for applicantsroot.
170    """
171    grok.context(IApplicantsRoot)
172    title = u'Applicants'
173
174class ApplicantsContainerBreadcrumb(Breadcrumb):
175    """A breadcrumb for applicantscontainers.
176    """
177    grok.context(IApplicantsContainer)
178
179class ApplicantsTab(PrimaryNavTab):
180    """Faculties-tab in primary navigation.
181    """
182
183    grok.context(IWAeUPObject)
184    grok.order(3)
185    grok.require('waeup.manageUniversity')
186    grok.template('primarynavtab')
187
188    pnav = 3
189    tab_title = u'Applicants'
190
191    @property
192    def link_target(self):
193        return self.view.application_url('applicants')
194
195class ApplicantsContainerPage(WAeUPDisplayFormPage):
196    """The standard view for regular applicant containers.
197    """
198    grok.context(IApplicantsContainer)
199    grok.name('index')
200    grok.template('applicantscontainerpage')
201    pnav = 3
202
203    form_fields = grok.AutoFields(IApplicantsContainer)
204    # Use friendlier date widget...
205    form_fields['startdate'].custom_widget = FriendlyDateDisplayWidget('le')
206    form_fields['enddate'].custom_widget = FriendlyDateDisplayWidget('le')
207    form_fields['description'].custom_widget = ReSTWidget
208
209    @property
210    def title(self):
211        return "Applicants Container: %s" % getattr(
212            self.context, '__name__', 'unnamed')
213
214    @property
215    def label(self):
216        return self.title
217
218
219class ManageApplicantsContainerActionButton(ManageActionButton):
220    grok.context(IApplicantsContainer)
221    grok.view(ApplicantsContainerPage)
222    text = 'Manage applicants container'
223
224
225class ManageApplicantsContainer(WAeUPEditFormPage):
226    grok.context(IApplicantsContainer)
227    grok.name('manage')
228    grok.template('form_manage_applicants_container')
229    form_fields = grok.AutoFields(IApplicantsContainer)
230    # Use friendlier date widget...
231    form_fields['startdate'].custom_widget = FriendlyDateWidget('le')
232    form_fields['enddate'].custom_widget = FriendlyDateWidget('le')
233
234    @property
235    def title(self):
236        return "Manage applicants container: %s" % getattr(
237            self.context, '__name__', 'unnamed')
238
239    @property
240    def label(self):
241        return self.title
242
243    pnav = 3
244
245    def update(self):
246        datepicker.need() # Enable jQuery datepicker in date fields.
247        tabs.need()
248        datatable.need()  # Enable jQurey datatables for contents listing
249        return super(ManageApplicantsContainer, self).update()
250
251    @grok.action('Save')
252    def apply(self, **data):
253        self.applyData(self.context, **data)
254        self.flash('Data saved.')
255        return
256
257    @grok.action('Back')
258    def cancel(self, **data):
259        self.redirect(self.url(self.context))
260        return
261
262class LoginApplicant(WAeUPPage):
263    grok.context(IApplicantsContainer)
264    grok.name('login')
265    grok.require('zope.Public')
266
267    title = u'Login'
268
269    @property
270    def label(self):
271        return self.title
272
273    pnav = 3
274    prefix = u'APP'
275
276    def update(self, SUBMIT=None):
277        self.ac_series = self.request.form.get('form.ac_series', None)
278        self.ac_number = self.request.form.get('form.ac_number', None)
279        if SUBMIT is None:
280            return
281
282        if self.request.principal.id == 'zope.anybody':
283            self.flash('Entered credentials are invalid')
284            return
285
286        if not IApplicantPrincipal.providedBy(self.request.principal):
287            # Don't care if user is already authenticated as non-applicant
288            return
289
290        pin = self.request.principal.access_code
291        if pin not in self.context.keys():
292            # Create applicant record
293            applicant = Applicant()
294            applicant.access_code = pin
295            self.context[pin] = applicant
296
297        # Assign current principal the owner role on created applicant
298        # record
299        role_manager = IPrincipalRoleManager(self.context)
300        role_manager.assignRoleToPrincipal(
301            'waeup.local.ApplicationOwner', self.request.principal.id)
302        self.redirect(self.url(self.context[pin], 'edit'))
303        return
304
305class DisplayApplicant(WAeUPDisplayFormPage):
306    grok.context(IApplicant)
307    grok.name('index')
308    grok.require('waeup.viewApplication')
309    form_fields = grok.AutoFields(IApplicant).omit('locked')
310    form_fields['fst_sit_results'].custom_widget = list_results_display_widget
311    form_fields['passport'].custom_widget = ThumbnailWidget
312    form_fields['date_of_birth'].custom_widget = FriendlyDateDisplayWidget('le')
313    label = 'Applicant'
314    title = 'Applicant'
315    pnav = 3
316
317class EditApplicantStudent(WAeUPEditFormPage):
318    """An applicant-centered edit view for applicant data.
319    """
320    grok.context(IApplicant)
321    grok.name('edit')
322    grok.require('waeup.editApplication')
323    form_fields = grok.AutoFields(IApplicantPDEEditData).omit('locked')
324    form_fields['passport'].custom_widget = EncodingImageFileWidget
325    form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
326    grok.template('form_edit_pde')
327
328    def emitLockMessage(self):
329        self.flash('The requested form is locked (read-only)')
330        self.redirect(self.url(self.context))
331        return
332
333    def update(self):
334        if self.context.locked:
335            self.emitLockMessage()
336            return
337        datepicker.need() # Enable jQuery datepicker in date fields.
338        super(EditApplicantStudent, self).update()
339        return
340
341    def filteredWidgets(self):
342        for widget in self.widgets:
343            if widget.name == 'form.confirm_passport':
344                continue
345            yield widget
346
347    @property
348    def label(self):
349        # XXX: Use current/upcoming session
350        return 'Apply for Post UDE Screening Test (2009/2010)'
351    title = 'Edit Application'
352    pnav = 3
353
354    @grok.action('Save')
355    def save(self, **data):
356        if self.context.locked:
357            self.emitLockMessage()
358            return
359        self.applyData(self.context, **data)
360        self.context._p_changed = True
361        return
362
363    @grok.action('Final Submit')
364    def finalsubmit(self, **data):
365        if self.context.locked:
366            self.emitLockMessage()
367            return
368        self.applyData(self.context, **data)
369        self.context._p_changed = True
370        if not self.dataComplete():
371            self.flash('Data yet not complete.')
372            return
373        self.context.locked = True
374        return
375
376    def dataComplete(self):
377        if self.context.confirm_passport is not True:
378            return False
379        if len(self.errors) > 0:
380            return False
381        return True
382
383class EditApplicantFull(WAeUPEditFormPage):
384    """A full edit view for applicant data.
385
386    This one is meant to be used by officers only.
387    """
388    grok.context(IApplicant)
389    grok.name('edit_full')
390    grok.require('waeup.editFullApplication')
391    form_fields = grok.AutoFields(IApplicantPDEEditData).omit('locked')
392    form_fields['passport'].custom_widget = EncodingImageFileWidget
393    form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
394    grok.template('form_edit_full')
395
396    def update(self):
397        if self.context.locked:
398            self.emitLockMessage()
399            return
400        datepicker.need() # Enable jQuery datepicker in date fields.
401        super(EditApplicantFull, self).update()
402        return
403
404    def filteredWidgets(self):
405        for widget in self.widgets:
406            if widget.name == 'form.confirm_passport':
407                continue
408            yield widget
409
410    @property
411    def label(self):
412        return 'Application for %s' % self.context.access_code
413    title = 'Edit Application'
414    pnav = 3
415
416    @grok.action('Save')
417    def save(self, **data):
418        self.applyData(self.context, **data)
419        self.context._p_changed = True
420        return
Note: See TracBrowser for help on using the repository browser.