source: main/kofacustom.edopoly/trunk/src/kofacustom/edopoly/applicants/browser.py @ 17959

Last change on this file since 17959 was 17370, checked in by Henrik Bettermann, 20 months ago

Implement transcript application.

  • Property svn:keywords set to Id
File size: 12.8 KB
RevLine 
[10765]1## $Id: browser.py 17370 2023-03-29 13:15:45Z 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"""
20import grok
[15123]21from time import time
[15087]22from zope.formlib.textwidgets import BytesDisplayWidget
[15123]23from zope.component import getUtility, createObject
24from hurry.workflow.interfaces import IWorkflowState
[10765]25from waeup.kofa.applicants.browser import (
[15123]26    ApplicantRegistrationPage, ApplicantsContainerPage,
[15319]27    ExportPDFPageApplicationSlip,
28    ExportJobContainerOverview,
29    ExportJobContainerJobStart,
30    ExportJobContainerDownload)
[15123]31from waeup.kofa.browser.layout import action, UtilityView
[10765]32from kofacustom.nigeria.applicants.browser import (
33    NigeriaApplicantDisplayFormPage,
[15087]34    NigeriaPDFApplicationSlip,
35    NigeriaApplicantManageFormPage,
[15319]36    NigeriaApplicantEditFormPage,
37    )
[15087]38from kofacustom.nigeria.applicants.interfaces import (
39    UG_OMIT_DISPLAY_FIELDS,
40    UG_OMIT_PDF_FIELDS,
41    UG_OMIT_MANAGE_FIELDS,
42    UG_OMIT_EDIT_FIELDS,
43    PG_OMIT_DISPLAY_FIELDS,
44    PG_OMIT_PDF_FIELDS,
45    PG_OMIT_MANAGE_FIELDS,
46    PG_OMIT_EDIT_FIELDS,
47    )
[15131]48from waeup.kofa.applicants.workflow import (
49    ADMITTED, PAID, STARTED, NOT_ADMITTED, CREATED)
[15087]50from kofacustom.edopoly.applicants.interfaces import (
51    ICustomUGApplicantEdit, ICustomUGApplicant,
[15123]52    ICustomPGApplicantEdit, ICustomPGApplicant,
[17370]53    ICustomApplicant, ICustomSpecialApplicant, ITranscriptApplicant)
[10765]54
[15000]55from kofacustom.edopoly.interfaces import MessageFactory as _
[10765]56
[15087]57# Fields to be omitted in all display forms. course_admitted is
58# rendered separately.
59
60OMIT_DISPLAY_FIELDS = ('locked', 'course_admitted',
61    'result_uploaded', 'suspended', 'special_application',
62    'bank_account_number',
63    'bank_account_name',
64    'bank_name')
65
66# UG students are all undergraduate students.
67UG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
[15170]68    #'jamb_subjects',
[15171]69    'programme_type',)
[15087]70UG_OMIT_PDF_FIELDS = UG_OMIT_DISPLAY_FIELDS + ('phone',)
71UG_OMIT_MANAGE_FIELDS = (
72    'special_application',
[15170]73    #'jamb_subjects',
[15087]74    'programme_type')
[15169]75UG_OMIT_EDIT_FIELDS = UG_OMIT_MANAGE_FIELDS + UG_OMIT_DISPLAY_FIELDS + (
[15087]76    'student_id',
77    'notice',
78    'screening_score',
79    'screening_venue',
80    'screening_date',
81    'aggregate')
82
[17370]83TRANS_OMIT_FIELDS = ('suspended',)
84
85TRANS_SHORT_OMIT_FIELDS = TRANS_OMIT_FIELDS
86
87TRANS_OMIT_EDIT_FIELDS = TRANS_OMIT_FIELDS + ('applicant_id', )
88
89TRANS_SHORT_OMIT_EDIT_FIELDS = TRANS_SHORT_OMIT_FIELDS + ('applicant_id', )
90
91TRANS_OMIT_PDF_FIELDS = TRANS_OMIT_FIELDS + ('locked', )
92
93TRANS_SHORT_OMIT_PDF_FIELDS = TRANS_SHORT_OMIT_FIELDS + ('locked', )
94
[15087]95class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage):
96    """A display view for applicant data.
97    """
[15123]98    grok.template('applicantdisplaypage')
[15087]99
100    @property
101    def form_fields(self):
102        target = getattr(self.context.__parent__, 'prefix', None)
[17370]103        if target is not None and target == 'tscf':
104            form_fields = grok.AutoFields(ITranscriptApplicant)
105            for field in TRANS_OMIT_FIELDS:
106                form_fields = form_fields.omit(field)
107            form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
108            #form_fields['perm_address'].custom_widget = BytesDisplayWidget
109            return form_fields
110        if target is not None and target == 'tscs':
111            form_fields = grok.AutoFields(ITranscriptApplicant)
112            for field in TRANS_SHORT_OMIT_FIELDS:
113                form_fields = form_fields.omit(field)
114            form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
115            #form_fields['perm_address'].custom_widget = BytesDisplayWidget
116            return form_fields
[15218]117        if self.context.special:
118            return grok.AutoFields(ICustomSpecialApplicant)
[15087]119        form_fields = grok.AutoFields(ICustomUGApplicant)
[15123]120        for field in UG_OMIT_DISPLAY_FIELDS:
121            form_fields = form_fields.omit(field)
[15087]122        form_fields['notice'].custom_widget = BytesDisplayWidget
[15169]123        #form_fields['jamb_subjects'].custom_widget = BytesDisplayWidget
[15087]124        if not getattr(self.context, 'student_id'):
125            form_fields = form_fields.omit('student_id')
126        if not getattr(self.context, 'screening_score'):
127            form_fields = form_fields.omit('screening_score')
128        if not getattr(self.context, 'screening_venue'):
129            form_fields = form_fields.omit('screening_venue')
130        if not getattr(self.context, 'screening_date'):
131            form_fields = form_fields.omit('screening_date')
[15123]132        if not self.context.admchecking_fee_paid():
133            form_fields = form_fields.omit(
134                'screening_score', 'aggregate', 'student_id')
[15087]135        return form_fields
136
[15123]137    @property
138    def admission_checking_info(self):
[15131]139        if self.context.state in (ADMITTED, NOT_ADMITTED, CREATED) and \
[15123]140            not self.context.admchecking_fee_paid():
141            return _('You must pay the admission checking fee '
[15124]142                     'to view your screening results and your course admitted.')
[15123]143
144    @property
145    def display_actions(self):
146        state = IWorkflowState(self.context).getState()
147        actions = []
[15131]148        if state in (ADMITTED, NOT_ADMITTED, CREATED) \
149            and not self.context.admchecking_fee_paid():
[15123]150            actions = [_('Add admission checking payment ticket')]
151        return actions
152
153    def getCourseAdmitted(self):
154        """Return link, title and code in html format to the certificate
155           admitted.
156        """
157        if self.admission_checking_info:
[15124]158            return '<span class="hint">%s</span>' % self.admission_checking_info
[15123]159        return super(CustomApplicantDisplayFormPage, self).getCourseAdmitted()
160
161    @action(_('Add admission checking payment ticket'), style='primary')
162    def addPaymentTicket(self, **data):
163        self.redirect(self.url(self.context, '@@addacp'))
164        return
165
166class AdmissionCheckingFeePaymentAddPage(UtilityView, grok.View):
167    """ Page to add an admission checking online payment ticket.
168    """
169    grok.context(ICustomApplicant)
170    grok.name('addacp')
171    grok.require('waeup.payApplicant')
172    factory = u'waeup.ApplicantOnlinePayment'
173
174    def _setPaymentDetails(self, payment):
175        container = self.context.__parent__
176        timestamp = ("%d" % int(time()*10000))[1:]
177        session = str(container.year)
178        try:
179            session_config = grok.getSite()['configuration'][session]
180        except KeyError:
181            return _(u'Session configuration object is not available.'), None
182        payment.p_id = "p%s" % timestamp
183        payment.p_item = container.title
184        payment.p_session = container.year
185        payment.amount_auth = 0.0
186        payment.p_category = 'admission_checking'
187        payment.amount_auth = session_config.admchecking_fee
188        if payment.amount_auth in (0.0, None):
189            return _('Amount could not be determined.'), None
190        return
191
192    def update(self):
193        if self.context.admchecking_fee_paid():
194              self.flash(
195                  _('Admission checking payment has already been made.'),
196                  type='warning')
197              self.redirect(self.url(self.context))
198              return
199        payment = createObject(self.factory)
200        failure = self._setPaymentDetails(payment)
201        if failure is not None:
202            self.flash(failure[0], type='danger')
203            self.redirect(self.url(self.context))
204            return
205        self.context[payment.p_id] = payment
206        self.flash(_('Payment ticket created.'))
207        self.redirect(self.url(payment))
208        return
209
210    def render(self):
211        return
212
213class CustomExportPDFPageApplicationSlip(ExportPDFPageApplicationSlip):
214    """Deliver a PDF slip of the context.
215    """
216
217    def update(self):
218        super(CustomExportPDFPageApplicationSlip, self).update()
[15131]219        if self.context.state in (ADMITTED, NOT_ADMITTED, CREATED) and \
[15123]220            not self.context.admchecking_fee_paid():
221            self.flash(
222                _('Please pay admission checking fee before trying to download '
223                  'the application slip.'), type='warning')
224            return self.redirect(self.url(self.context))
225        return
226
[15087]227class CustomPDFApplicationSlip(NigeriaPDFApplicationSlip):
228
229    @property
230    def form_fields(self):
231        target = getattr(self.context.__parent__, 'prefix', None)
232        form_fields = grok.AutoFields(ICustomUGApplicant)
233        for field in UG_OMIT_PDF_FIELDS:
234            form_fields = form_fields.omit(field)
235        if not getattr(self.context, 'student_id'):
236            form_fields = form_fields.omit('student_id')
237        if not getattr(self.context, 'screening_score'):
238            form_fields = form_fields.omit('screening_score')
239        if not getattr(self.context, 'screening_venue'):
240            form_fields = form_fields.omit('screening_venue')
241        if not getattr(self.context, 'screening_date'):
242            form_fields = form_fields.omit('screening_date')
243        return form_fields
244
245class CustomApplicantManageFormPage(NigeriaApplicantManageFormPage):
246    """A full edit view for applicant data.
247    """
248
249    @property
250    def form_fields(self):
[17370]251        target = getattr(self.context.__parent__, 'prefix', None)
252        if target is not None and target == 'tscf':
253            form_fields = grok.AutoFields(ITranscriptApplicant)
254            for field in TRANS_OMIT_EDIT_FIELDS:
255                form_fields = form_fields.omit(field)
256            return form_fields
257        if target is not None and target == 'tscs':
258            form_fields = grok.AutoFields(ITranscriptApplicant)
259            for field in TRANS_SHORT_OMIT_EDIT_FIELDS:
260                form_fields = form_fields.omit(field)
261            return form_fields
[15218]262        if self.context.special:
263            form_fields = grok.AutoFields(ICustomSpecialApplicant)
264            form_fields['applicant_id'].for_display = True
265            return form_fields
[15087]266        form_fields = grok.AutoFields(ICustomUGApplicant)
267        for field in UG_OMIT_MANAGE_FIELDS:
268            form_fields = form_fields.omit(field)
269        form_fields['student_id'].for_display = True
270        form_fields['applicant_id'].for_display = True
271        return form_fields
272
273class CustomApplicantEditFormPage(NigeriaApplicantEditFormPage):
274    """An applicant-centered edit view for applicant data.
275    """
276
277    @property
278    def form_fields(self):
[17370]279        target = getattr(self.context.__parent__, 'prefix', None)
280        state = IWorkflowState(self.context).getState()
281        if target is not None and target == 'tscf':
282            form_fields = grok.AutoFields(ITranscriptApplicant)
283            form_fields['courier_tno'].for_display = True
284            form_fields['proc_date'].for_display = True
285            for field in TRANS_OMIT_EDIT_FIELDS:
286                form_fields = form_fields.omit(field)
287            if state == PAID:
288                form_fields['order'].for_display = True
289            form_fields = form_fields.omit('locked')
290            return form_fields
291        if target is not None and target == 'tscs':
292            form_fields = grok.AutoFields(ITranscriptApplicant)
293            form_fields['courier_tno'].for_display = True
294            form_fields['proc_date'].for_display = True
295            for field in TRANS_SHORT_OMIT_EDIT_FIELDS:
296                form_fields = form_fields.omit(field)
297            form_fields = form_fields.omit('locked')
298            if state == PAID:
299                form_fields['order'].for_display = True
300            return form_fields
[15218]301        if self.context.special:
302            form_fields = grok.AutoFields(ICustomSpecialApplicant).omit(
303                'locked', 'suspended')
304            form_fields['applicant_id'].for_display = True
305            return form_fields
[15087]306        form_fields = grok.AutoFields(ICustomUGApplicantEdit)
307        for field in UG_OMIT_EDIT_FIELDS:
308            form_fields = form_fields.omit(field)
309        form_fields['applicant_id'].for_display = True
310        form_fields['reg_number'].for_display = True
311        return form_fields
[15319]312
313class CustomExportJobContainerOverview(ExportJobContainerOverview):
314
315    grok.require('waeup.viewApplication')
316
317class CustomExportJobContainerJobStart(ExportJobContainerJobStart):
318
319    grok.require('waeup.viewApplication')
320
321class CustomExportJobContainerDownload(ExportJobContainerDownload):
322
323    grok.require('waeup.viewApplication')
Note: See TracBrowser for help on using the repository browser.