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

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

In the morning everything looks easier.

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