source: main/waeup.uniben/trunk/src/waeup/uniben/applicants/browser.py @ 13998

Last change on this file since 13998 was 13947, checked in by Henrik Bettermann, 9 years ago

PUTME is obsolete. Rename putme to ase (Admission Screening Exercise). Use new links for past question pdf files.

  • Property svn:keywords set to Id
File size: 15.3 KB
RevLine 
[8012]1## $Id: browser.py 13947 2016-06-15 14:45:38Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""UI components for basic applicants and related components.
19"""
[10287]20import grok
[11784]21from time import time
[11782]22from zope.component import getUtility, createObject
[11736]23from zope.security import checkPermission
[13552]24from zope.i18n import translate
[11784]25from hurry.workflow.interfaces import IWorkflowState
26from waeup.kofa.browser.layout import action, UtilityView
[13552]27from waeup.kofa.interfaces import IExtFileStore, IKofaUtils
[10587]28from waeup.kofa.applicants.browser import (
[11728]29    ApplicantRegistrationPage, ApplicantsContainerPage,
[11782]30    ApplicationFeePaymentAddPage,
[11784]31    OnlinePaymentApprovePage,
32    ExportPDFPageApplicationSlip)
[11782]33from waeup.kofa.applicants.interfaces import (
34    ISpecialApplicant, IApplicantsUtils)
[13558]35from waeup.kofa.browser.interfaces import IPDFCreator
[10378]36from kofacustom.nigeria.applicants.browser import (
37    NigeriaApplicantDisplayFormPage,
[11736]38    NigeriaApplicantManageFormPage,
[13796]39    NigeriaApplicantEditFormPage,
[10378]40    NigeriaPDFApplicationSlip)
[11782]41from waeup.uniben.applicants.interfaces import (
[13814]42    ICustomApplicant, IUnibenRegistration)
[13825]43from waeup.kofa.applicants.workflow import ADMITTED, PAID, STARTED
[8012]44
[10378]45from waeup.uniben.interfaces import MessageFactory as _
46
[10338]47PASTQ_ALL = ['ADT','EPCS','ESM','HEK','VTE']
[8012]48
[10338]49PASTQ_AL = ['ENL','FAA','FOL','HIS','LAL',
50            'PHL','THR','BUL','JIL','LAW','PPL','PUL'] + PASTQ_ALL
51
52PASTQ_BS = ['ANT','ANY','CHH','COH','HAE','MED','MEH','PHS','SUR',
53            'PCG','PCH','PCO', 'PCT','PHA','PHM','PMB','ANA','MBC',
54            'MLS','NSC','PSY','DPV','ODR','OSP','PER', 'RES','AEB',
55            'BCH','BOT','CED','EVL','MCB','OPT','PBB','SLT','ZOO',
56            'AEE','ANS', 'CRS','FIS','FOW','SOS'] + PASTQ_ALL
57
58PASTQ_EPS = ['CHE','CVE','DMIC','EEE','MCH','PEE','PRE','CHM',
59             'CSC','GLY','MTH','PHY'] + PASTQ_ALL
60
61PASTQ_MSS = ['ACC','BNK','BUS','ECO','GEO','POL','SAA','SWK'] + PASTQ_ALL
62
[13814]63REGISTRATION_OMIT_DISPLAY_FIELDS = (
64    'locked',
65    'suspended',
[13796]66    )
67
[13814]68REGISTRATION_OMIT_EDIT_FIELDS = (
69    'locked',
70    'suspended',
71    'applicant_id',
72    )
73
74REGISTRATION_OMIT_MANAGE_FIELDS = (
75    'applicant_id',
76    )
77
78
79REGISTRATION_OMIT_PDF_FIELDS = (
80    'locked',
81    'suspended',
82    )
[10587]83class CustomApplicantsContainerPage(ApplicantsContainerPage):
84    """The standard view for regular applicant containers.
85    """
86
87    @property
88    def form_fields(self):
89        form_fields = super(CustomApplicantsContainerPage, self).form_fields
[10589]90        usertype = getattr(self.request.principal, 'user_type', None)
91        if self.request.principal.id == 'zope.anybody' or  \
92            usertype in ('applicant', 'student'):
[10587]93            return form_fields.omit('application_fee')
94        return form_fields
95
[8630]96class CustomApplicantRegistrationPage(ApplicantRegistrationPage):
97    """Captcha'd registration page for applicants.
98    """
99
[10337]100    def _redirect(self, email, password, applicant_id):
101        # Forward email and credentials to landing page.
102        self.redirect(self.url(self.context, 'registration_complete',
103            data = dict(email=email, password=password,
104            applicant_id=applicant_id)))
105        return
[10287]106
[10375]107class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage):
108    """A display view for applicant data.
[10287]109    """
[10375]110    grok.template('applicantdisplaypage')
[10338]111
[13887]112    @property
113    def display_payments(self):
114        if self.context.special or self.target == 'ictwk':
115            return True
116        return getattr(self.context.__parent__, 'application_fee', None)
117
[10622]118    def _show_pastq_putme(self):
[13947]119        return self.target.startswith('ase') \
[10375]120               and self.context.state in ('paid', 'submitted') \
[10338]121               and getattr(self.context, 'course1') is not None
122
123    @property
124    def show_pastq_al(self):
[10622]125        return self._show_pastq_putme() \
[10338]126               and self.context.course1.__parent__.__parent__.code in PASTQ_AL
127
128    @property
129    def show_pastq_bs(self):
[10622]130        return self._show_pastq_putme() \
[10338]131               and self.context.course1.__parent__.__parent__.code in PASTQ_BS
132
133    @property
134    def show_pastq_eps(self):
[10622]135        return self._show_pastq_putme() \
[10338]136               and self.context.course1.__parent__.__parent__.code in PASTQ_EPS
137
138    @property
139    def show_pastq_mss(self):
[10622]140        return self._show_pastq_putme() \
[10338]141               and self.context.course1.__parent__.__parent__.code in PASTQ_MSS
142
[10622]143    @property
144    def show_pastq_pude(self):
145        return self.target.startswith('pude') \
146               and self.context.state in ('paid', 'submitted')
147
[13814]148    @property
149    def label(self):
150        if self.target == 'ictwk':
151            container_title = self.context.__parent__.title
152            return _('${a} <br /> Registration Record ${b}', mapping = {
153                'a':container_title, 'b':self.context.application_number})
154        return super(CustomApplicantDisplayFormPage, self).label
[11784]155
[11782]156    @property
157    def form_fields(self):
[13796]158        if self.target == 'ictwk':
[13814]159            form_fields = grok.AutoFields(IUnibenRegistration)
160            for field in REGISTRATION_OMIT_DISPLAY_FIELDS:
[13796]161                form_fields = form_fields.omit(field)
162            return form_fields
[13814]163        form_fields = super(CustomApplicantDisplayFormPage, self).form_fields
[11784]164        if not self.context.admchecking_fee_paid():
165            form_fields = form_fields.omit(
166                'screening_score', 'aggregate', 'student_id')
[11782]167        return form_fields
168
[11784]169    @property
170    def display_actions(self):
171        state = IWorkflowState(self.context).getState()
172        actions = []
173        if state == ADMITTED and not self.context.admchecking_fee_paid():
174            actions = [_('Add admission checking payment ticket')]
175        return actions
176
177
178    def getCourseAdmitted(self):
179        """Return link, title and code in html format to the certificate
180           admitted.
181        """
182        course_admitted = self.context.course_admitted
183        if getattr(course_admitted, '__parent__',None) and \
184            self.context.admchecking_fee_paid():
185            url = self.url(course_admitted)
186            title = course_admitted.title
187            code = course_admitted.code
188            return '<a href="%s">%s - %s</a>' %(url,code,title)
189        return ''
190
[11786]191    @property
192    def admission_checking_info(self):
193        if self.context.state == ADMITTED and \
194            not self.context.admchecking_fee_paid():
195            return _('You must pay the admission checking fee '
196                     'to view your screening results and course admitted.')
197        return
198
[11784]199    @action(_('Add admission checking payment ticket'), style='primary')
200    def addPaymentTicket(self, **data):
201        self.redirect(self.url(self.context, '@@addacp'))
202        return
203
[11728]204class CustomApplicationFeePaymentAddPage(ApplicationFeePaymentAddPage):
205    """ Page to add an online payment ticket
206    """
[10378]207
[11728]208    @property
209    def custom_requirements(self):
210        store = getUtility(IExtFileStore)
211        if not store.getFileByContext(self.context, attr=u'passport.jpg'):
[11782]212            return _('Upload your 1"x1" Red background passport photo before making payment.')
[11728]213        return ''
214
[11784]215class AdmissionCheckingFeePaymentAddPage(UtilityView, grok.View):
216    """ Page to add an admission checking online payment ticket.
217    """
218    grok.context(ICustomApplicant)
219    grok.name('addacp')
220    grok.require('waeup.payApplicant')
221    factory = u'waeup.ApplicantOnlinePayment'
222
223    def _setPaymentDetails(self, payment):
224        container = self.context.__parent__
225        timestamp = ("%d" % int(time()*10000))[1:]
226        session = str(container.year)
227        try:
228            session_config = grok.getSite()['configuration'][session]
229        except KeyError:
230            return _(u'Session configuration object is not available.'), None
231        payment.p_id = "p%s" % timestamp
232        payment.p_item = container.title
233        payment.p_session = container.year
234        payment.amount_auth = 0.0
235        payment.p_category = 'admission_checking'
236        payment.amount_auth = session_config.admchecking_fee
237        if payment.amount_auth in (0.0, None):
238            return _('Amount could not be determined.'), None
239        return
240
[11782]241    def update(self):
[11784]242        if self.context.admchecking_fee_paid():
243              self.flash(
244                  _('Admission checking payment has already been made.'),
245                  type='warning')
246              self.redirect(self.url(self.context))
247              return
[11782]248        payment = createObject(self.factory)
[11784]249        failure = self._setPaymentDetails(payment)
[11782]250        if failure is not None:
251            self.flash(failure[0], type='danger')
252            self.redirect(self.url(self.context))
253            return
254        self.context[payment.p_id] = payment
255        self.flash(_('Payment ticket created.'))
256        self.redirect(self.url(payment))
257        return
[11736]258
[11784]259    def render(self):
260        return
[11736]261
[11784]262
[11782]263class CustomApplicantManageFormPage(NigeriaApplicantManageFormPage):
264
[11736]265    @property
[13887]266    def display_payments(self):
267        if self.context.special or self.target == 'ictwk':
268            return True
269        return getattr(self.context.__parent__, 'application_fee', None)
270
271    @property
[11736]272    def custom_upload_requirements(self):
273        if not checkPermission('waeup.uploadPassportPictures', self.context):
274            return _('You are not entitled to upload passport pictures.')
[11782]275
[13796]276    @property
[13814]277    def label(self):
278        if self.target == 'ictwk':
279            container_title = self.context.__parent__.title
280            return _('${a} <br /> Registration Record ${b}', mapping = {
281                'a':container_title, 'b':self.context.application_number})
282        return super(CustomApplicantManageFormPage, self).label
283
284    @property
[13796]285    def form_fields(self):
286        if self.target == 'ictwk':
[13814]287            form_fields = grok.AutoFields(IUnibenRegistration)
288            for field in REGISTRATION_OMIT_MANAGE_FIELDS:
[13796]289                form_fields = form_fields.omit(field)
[13825]290            state = IWorkflowState(self.context).getState()
291            if state != STARTED:
292                form_fields['registration_cats'].for_display = True
[13814]293            return form_fields
294        form_fields = super(CustomApplicantManageFormPage, self).form_fields
[13796]295        return form_fields
296
297
298class CustomApplicantEditFormPage(NigeriaApplicantEditFormPage):
299    """An applicant-centered edit view for applicant data.
300    """
301
302    @property
[13887]303    def display_payments(self):
304        if self.context.special or self.target == 'ictwk':
305            return True
306        return getattr(self.context.__parent__, 'application_fee', None)
307
308    @property
[13796]309    def form_fields(self):
310        if self.target == 'ictwk':
[13814]311            form_fields = grok.AutoFields(IUnibenRegistration)
312            for field in REGISTRATION_OMIT_EDIT_FIELDS:
[13796]313                form_fields = form_fields.omit(field)
[13825]314            state = IWorkflowState(self.context).getState()
315            if state != STARTED:
316                form_fields['registration_cats'].for_display = True
[13814]317            return form_fields
318        form_fields = super(CustomApplicantEditFormPage, self).form_fields
[13796]319        return form_fields
320
[13814]321    @property
322    def label(self):
323        if self.target == 'ictwk':
324            container_title = self.context.__parent__.title
325            return _('${a} <br /> Registration Record ${b}', mapping = {
326                'a':container_title, 'b':self.context.application_number})
327        return super(CustomApplicantEditFormPage, self).label
328
[11782]329class CustomOnlinePaymentApprovePage(OnlinePaymentApprovePage):
330    """ Approval view
331    """
332
333    def update(self):
[11784]334        if self.context.p_category == 'admission_checking':
335            if self.context.p_state == 'paid':
336                flashtype = 'warning'
337                msg = _('This ticket has already been paid.')
338                log = None
339            else:
340                self.context.approve()
341                log = 'payment approved: %s' % self.context.p_id
342                msg = _('Payment approved')
343                flashtype = 'success'
344        else:
345            flashtype, msg, log = self.context.approveApplicantPayment()
[11782]346        if log is not None:
347            applicant = self.context.__parent__
348            # Add log message to applicants.log
349            applicant.writeLogMessage(self, log)
350            # Add log message to payments.log
351            self.context.logger.info(
352                '%s,%s,%s,%s,%s,,,,,,' % (
353                applicant.applicant_id,
354                self.context.p_id, self.context.p_category,
355                self.context.amount_auth, self.context.r_code))
356        self.flash(msg, type=flashtype)
357        return
[11784]358
359class CustomExportPDFPageApplicationSlip(ExportPDFPageApplicationSlip):
360    """Deliver a PDF slip of the context.
361    """
362
363    def update(self):
364        super(CustomExportPDFPageApplicationSlip, self).update()
365        if self.context.state == ADMITTED and \
366            not self.context.admchecking_fee_paid():
367            self.flash(
368                _('Please pay admission checking fee before trying to download '
369                  'the application slip.'), type='warning')
370            return self.redirect(self.url(self.context))
371        return
[13552]372
[13557]373class CustomPDFApplicationSlip(NigeriaPDFApplicationSlip):
[13552]374
[13558]375    def _getPDFCreator(self):
376        if 'afak' in self.target:
377            return getUtility(IPDFCreator, name='akoka_pdfcreator')
378        return getUtility(IPDFCreator)
379
[13552]380    @property
[13814]381    def form_fields(self):
382        if self.target == 'ictwk':
383            form_fields = grok.AutoFields(IUnibenRegistration)
384            for field in REGISTRATION_OMIT_PDF_FIELDS:
385                form_fields = form_fields.omit(field)
386            return form_fields
387        form_fields = super(CustomPDFApplicationSlip, self).form_fields
388        return form_fields
389
390    @property
[13552]391    def title(self):
392        container_title = self.context.__parent__.title
393        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
394        ar_translation = translate(_('Application Record'),
395            'waeup.kofa', target_language=portal_language)
[13814]396        if self.target == 'ictwk':
397            return '%s - Registration Record %s' % (container_title,
398            self.context.application_number)
399        elif 'afas' in self.target:
[13552]400            return 'Federal College of Education (Technical) Asaba - %s %s %s' % (
401                container_title, ar_translation,
402                self.context.application_number)
[13615]403        elif 'afak' in self.target:
[13552]404            return 'Federal College of Education (Technical) Akoka - %s %s %s' % (
405                container_title, ar_translation,
406                self.context.application_number)
[13615]407        elif self.target == 'pgn':
408            return 'National Institute for Legislative Studies (NILS) - %s %s %s' % (
409                container_title, ar_translation,
410                self.context.application_number)
[13552]411        return '%s - %s %s' % (container_title,
412            ar_translation, self.context.application_number)
Note: See TracBrowser for help on using the repository browser.