source: main/waeup.kofa/trunk/src/waeup/kofa/students/viewlets.py @ 9690

Last change on this file since 9690 was 9521, checked in by Henrik Bettermann, 12 years ago

Rename is_fresh method. Actually we need to filter students who have not yet paid school fee.

  • Property svn:keywords set to Id
File size: 29.2 KB
RevLine 
[9138]13## $Id: viewlets.py 9521 2012-11-04 08:04:15Z henrik $
[7191]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##
[7106]18import os
[6642]19import grok
[7097]20from zope.component import getUtility
[6642]21from zope.interface import Interface
[7741]22from zope.i18n import translate
[7811]23from waeup.kofa.interfaces import (
[8467]24    IKofaObject, IExtFileStore, IFileStoreNameChooser)
[7811]25from waeup.kofa.interfaces import MessageFactory as _
26from waeup.kofa.utils.helpers import string_from_bytes, file_size
27from waeup.kofa.browser import DEFAULT_IMAGE_PATH
28from waeup.kofa.browser.viewlets import (
[7591]29    PrimaryNavTab, ManageActionButton, AddActionButton)
[8106]30from waeup.kofa.browser.layout import (
[8467]31    default_primary_nav_template, default_filedisplay_template,
32    default_fileupload_template)
33from waeup.kofa.students.workflow import (
34    ADMITTED, PAID, REQUESTED, RETURNING, CLEARED, REGISTERED,
35    VALIDATED)
[7811]36from waeup.kofa.students.browser import (
[8735]37    StudentClearanceManageFormPage,
[8467]38    StudentBaseManageFormPage, StudentFilesUploadPage,
39    ExportPDFClearanceSlipPage, StudentsContainerPage,
[7591]40    StudentsContainerManagePage, StudentBaseDisplayFormPage,
41    StudentClearanceDisplayFormPage, StudentPersonalDisplayFormPage,
42    StudyCourseDisplayFormPage, StudyLevelDisplayFormPage,
43    CourseTicketDisplayFormPage, OnlinePaymentDisplayFormPage,
[8119]44    AccommodationManageFormPage, BedTicketDisplayFormPage,
[9517]45    StudentClearanceEditFormPage, StudentPersonalEditFormPage,
46    PaymentsManageFormPage)
[7811]47from waeup.kofa.students.interfaces import (
[8467]48    IStudentsContainer, IStudent, IStudentStudyCourse, IStudentAccommodation,
49    IStudentStudyLevel, ICourseTicket, IStudentOnlinePayment, IBedTicket,
[9517]50    IStudentPaymentsContainer,
[7591]51    )
[8467]52from waeup.kofa.utils.helpers import get_fileformat
[6642]53
[7819]54grok.context(IKofaObject) # Make IKofaObject the default context
[6687]55grok.templatedir('browser_templates')
[6642]56
[7123]57ALLOWED_FILE_EXTENSIONS = ('jpg', 'png', 'pdf', 'tif')
58
[6687]59class StudentManageSidebar(grok.ViewletManager):
60    grok.name('left_studentmanage')
[6642]61
[6687]62class StudentManageLink(grok.Viewlet):
[6660]63    """A link displayed in the student box which shows up for StudentNavigation
[6642]64    objects.
65
66    """
67    grok.baseclass()
[6687]68    grok.viewletmanager(StudentManageSidebar)
[7819]69    grok.context(IKofaObject)
[6642]70    grok.view(Interface)
71    grok.order(5)
[6660]72    grok.require('waeup.viewStudent')
[6642]73
74    link = 'index'
[7738]75    text = _(u'Base Data')
[6642]76
77    def render(self):
[8736]78        url = self.view.url(self.context.student, self.link)
[7833]79        # Here we know that the cookie has been set
80        lang = self.request.cookies.get('kofa.language')
[7811]81        text = translate(self.text, 'waeup.kofa',
[7741]82            target_language=lang)
[7459]83        return u'<li><a href="%s">%s</a></li>' % (
[7741]84                url, text)
[6642]85
[7459]86class StudentManageApplicationLink(StudentManageLink):
[6687]87    grok.order(1)
[7351]88    link = 'application_slip'
[7738]89    text = _(u'Application Slip')
[7340]90
91    def render(self):
[7351]92        slip = getUtility(IExtFileStore).getFileByContext(
[8736]93            self.context.student, attr=self.link)
[7351]94        if slip:
[9397]95            url = self.view.url(self.context.student,self.link)
[7459]96            return u'<li><a href="%s">%s</a></li>' % (
[7340]97                    url, self.text)
98        return ''
99
[7459]100class StudentManageBaseLink(StudentManageLink):
101    grok.order(2)
102    link = 'index'
[7738]103    text = _(u'Base Data')
[7459]104
[6687]105class StudentManageClearanceLink(StudentManageLink):
[7340]106    grok.order(3)
[6687]107    link = 'view_clearance'
[7738]108    text = _(u'Clearance Data')
[6687]109
110class StudentManagePersonalLink(StudentManageLink):
[7340]111    grok.order(4)
[6687]112    link = 'view_personal'
[7738]113    text = _(u'Personal Data')
[6687]114
115class StudentManageStudyCourseLink(StudentManageLink):
[7340]116    grok.order(5)
[6687]117    link = 'studycourse'
[7738]118    text = _(u'Study Course')
[6687]119
120class StudentManagePaymentsLink(StudentManageLink):
[7340]121    grok.order(6)
[7181]122    grok.require('waeup.payStudent')
[6687]123    link = 'payments'
[7738]124    text = _(u'Payments')
[6687]125
126class StudentManageAccommodationLink(StudentManageLink):
[7340]127    grok.order(7)
[7181]128    grok.require('waeup.handleAccommodation')
[6687]129    link = 'accommodation'
[7738]130    text = _(u'Accommodation')
[6687]131
132class StudentManageHistoryLink(StudentManageLink):
[7340]133    grok.order(8)
[6687]134    link = 'history'
[7738]135    text = _(u'History')
[6687]136
[7591]137
138class StudentsContainerManageActionButton(ManageActionButton):
139    grok.order(1)
140    grok.context(IStudentsContainer)
141    grok.view(StudentsContainerPage)
142    grok.require('waeup.manageStudent')
[7738]143    text = _('Manage student section')
[7591]144
145class StudentsContainerAddActionButton(AddActionButton):
146    grok.order(1)
147    grok.context(IStudentsContainer)
148    grok.view(StudentsContainerManagePage)
149    grok.require('waeup.manageStudent')
[7738]150    text = _('Add student')
[7591]151    target = 'addstudent'
152
153class ContactActionButton(ManageActionButton):
[9191]154    grok.order(5)
[7591]155    grok.context(IStudent)
156    grok.view(StudentBaseDisplayFormPage)
157    grok.require('waeup.manageStudent')
158    icon = 'actionicon_mail.png'
[7738]159    text = _('Send email')
[7591]160    target = 'contactstudent'
161
162class StudentBaseManageActionButton(ManageActionButton):
163    grok.order(1)
164    grok.context(IStudent)
165    grok.view(StudentBaseDisplayFormPage)
166    grok.require('waeup.manageStudent')
[7738]167    text = _('Manage')
[7591]168    target = 'manage_base'
169
[9273]170class StudentTrigTransActionButton(ManageActionButton):
171    grok.order(2)
172    grok.context(IStudent)
173    grok.view(StudentBaseDisplayFormPage)
174    grok.require('waeup.triggerTransition')
175    icon = 'actionicon_trigtrans.png'
176    text = _(u'Trigger transition')
177    target = 'trigtrans'
178
[9338]179class StudentLoginAsActionButton(ManageActionButton):
180    grok.order(3)
181    grok.context(IStudent)
182    grok.view(StudentBaseDisplayFormPage)
183    grok.require('waeup.loginAsStudent')
184    icon = 'actionicon_mask.png'
185    text = _(u'Login as student')
186    target = 'loginasstep1'
187
[9191]188class AdmissionSlipActionButton(ManageActionButton):
189    grok.order(4)
190    grok.context(IStudent)
191    grok.view(StudentBaseDisplayFormPage)
192    grok.require('waeup.viewStudent')
193    icon = 'actionicon_pdf.png'
194    text = _('Download admission letter')
195    target = 'admission_slip.pdf'
196
[9138]197class StudentTransfernButton(ManageActionButton):
[9191]198    grok.order(6)
[9124]199    grok.context(IStudent)
200    grok.view(StudentBaseDisplayFormPage)
201    grok.require('waeup.manageStudent')
[9138]202    text = _('Transfer student')
203    target = 'transfer'
204    icon = 'actionicon_redo.png'
205
206class StudentDeactivateActionButton(ManageActionButton):
[9191]207    grok.order(7)
[9138]208    grok.context(IStudent)
209    grok.view(StudentBaseDisplayFormPage)
210    grok.require('waeup.manageStudent')
[9124]211    text = _('Deactivate account')
212    target = 'deactivate'
213    icon = 'actionicon_traffic_lights_red.png'
214
215    @property
216    def target_url(self):
217        if self.context.suspended:
218            return ''
219        return self.view.url(self.view.context, self.target)
220
[9145]221    @property
222    def onclick(self):
223        return "return window.confirm(%s);" % _(
224            "'A history message will be added. Are you sure?'")
225
[9124]226class StudentActivateActionButton(ManageActionButton):
[9191]227    grok.order(7)
[9124]228    grok.context(IStudent)
229    grok.view(StudentBaseDisplayFormPage)
230    grok.require('waeup.manageStudent')
231    text = _('Activate account')
232    target = 'activate'
233    icon = 'actionicon_traffic_lights_green.png'
234
235    @property
236    def target_url(self):
237        if not self.context.suspended:
238            return ''
239        return self.view.url(self.view.context, self.target)
240
[9145]241    @property
242    def onclick(self):
243        return "return window.confirm(%s);" % _(
244            "'A history message will be added. Are you sure?'")
245
[7591]246class StudentClearanceManageActionButton(ManageActionButton):
247    grok.order(1)
248    grok.context(IStudent)
249    grok.view(StudentClearanceDisplayFormPage)
250    grok.require('waeup.manageStudent')
[7738]251    text = _('Manage')
[8119]252    target = 'manage_clearance'
[7591]253
254class StudentClearActionButton(ManageActionButton):
255    grok.order(2)
256    grok.context(IStudent)
257    grok.view(StudentClearanceDisplayFormPage)
258    grok.require('waeup.clearStudent')
[7738]259    text = _('Clear student')
[7591]260    target = 'clear'
261    icon = 'actionicon_accept.png'
262
263    @property
264    def target_url(self):
265        if self.context.state != REQUESTED:
266            return ''
267        return self.view.url(self.view.context, self.target)
268
269class StudentRejectClearanceActionButton(ManageActionButton):
270    grok.order(3)
271    grok.context(IStudent)
272    grok.view(StudentClearanceDisplayFormPage)
273    grok.require('waeup.clearStudent')
[7738]274    text = _('Reject clearance')
[7591]275    target = 'reject_clearance'
276    icon = 'actionicon_reject.png'
277
278    @property
279    def target_url(self):
280        if self.context.state not in (REQUESTED, CLEARED):
281            return ''
282        return self.view.url(self.view.context, self.target)
283
284class ClearanceSlipActionButton(ManageActionButton):
285    grok.order(4)
286    grok.context(IStudent)
287    grok.view(StudentClearanceDisplayFormPage)
288    grok.require('waeup.viewStudent')
289    icon = 'actionicon_pdf.png'
[7738]290    text = _('Download clearance slip')
[9452]291    target = 'clearance_slip.pdf'
[7591]292
[8119]293class ClearanceViewActionButton(ManageActionButton):
294    grok.order(1)
295    grok.context(IStudent)
296    grok.view(StudentClearanceEditFormPage)
297    grok.require('waeup.viewStudent')
298    icon = 'actionicon_view.png'
299    text = _('View')
300    target = 'view_clearance'
301
302class PersonalViewActionButton(ManageActionButton):
303    grok.order(1)
304    grok.context(IStudent)
305    grok.view(StudentPersonalEditFormPage)
306    grok.require('waeup.viewStudent')
307    icon = 'actionicon_view.png'
308    text = _('View')
309    target = 'view_personal'
310
[8903]311class StudentPersonalManageActionButton(ManageActionButton):
[7591]312    grok.order(1)
313    grok.context(IStudent)
314    grok.view(StudentPersonalDisplayFormPage)
[8903]315    grok.require('waeup.manageStudent')
316    text = _('Manage')
317    target = 'manage_personal'
318
319class StudentPersonalEditActionButton(ManageActionButton):
320    grok.order(2)
321    grok.context(IStudent)
322    grok.view(StudentPersonalDisplayFormPage)
323    grok.require('waeup.handleStudent')
[7738]324    text = _('Edit')
[7591]325    target = 'edit_personal'
326
327class StudyCourseManageActionButton(ManageActionButton):
328    grok.order(1)
329    grok.context(IStudentStudyCourse)
330    grok.view(StudyCourseDisplayFormPage)
331    grok.require('waeup.manageStudent')
[7738]332    text = _('Manage')
[7591]333    target = 'manage'
334
[9138]335    @property
336    def target_url(self):
337        if self.context.is_current:
338            return self.view.url(self.view.context, self.target)
339        return False
340
[8078]341class StudyLevelManageActionButton(ManageActionButton):
[7591]342    grok.order(1)
343    grok.context(IStudentStudyLevel)
344    grok.view(StudyLevelDisplayFormPage)
345    grok.require('waeup.manageStudent')
[7738]346    text = _('Manage')
[7591]347    target = 'manage'
348
[9138]349    @property
350    def target_url(self):
351        is_current = self.context.__parent__.is_current
352        if not is_current:
353            return ''
354        return self.view.url(self.view.context, self.target)
355
[7591]356class StudentValidateCoursesActionButton(ManageActionButton):
357    grok.order(3)
358    grok.context(IStudentStudyLevel)
359    grok.view(StudyLevelDisplayFormPage)
360    grok.require('waeup.validateStudent')
[7738]361    text = _('Validate courses')
[7591]362    target = 'validate_courses'
363    icon = 'actionicon_accept.png'
364
365    @property
366    def target_url(self):
[9138]367        is_current = self.context.__parent__.is_current
[8736]368        if self.context.student.state != REGISTERED or \
[9138]369            str(self.context.__parent__.current_level) != self.context.__name__ or\
370            not is_current:
[7591]371            return ''
372        return self.view.url(self.view.context, self.target)
373
374class StudentRejectCoursesActionButton(ManageActionButton):
375    grok.order(4)
376    grok.context(IStudentStudyLevel)
377    grok.view(StudyLevelDisplayFormPage)
378    grok.require('waeup.validateStudent')
[7738]379    text = _('Reject courses')
[7591]380    target = 'reject_courses'
381    icon = 'actionicon_reject.png'
382
383    @property
384    def target_url(self):
[9138]385        is_current = self.context.__parent__.is_current
[8736]386        if self.context.student.state not in (VALIDATED, REGISTERED) or \
[9138]387            str(self.context.__parent__.current_level) != self.context.__name__ or\
388            not is_current:
[7591]389            return ''
390        return self.view.url(self.view.context, self.target)
391
[8078]392class CourseRegistrationSlipActionButton(ManageActionButton):
393    grok.order(5)
394    grok.context(IStudentStudyLevel)
395    grok.view(StudyLevelDisplayFormPage)
396    grok.require('waeup.viewStudent')
397    icon = 'actionicon_pdf.png'
398    text = _('Download course registration slip')
[9452]399    target = 'course_registration_slip.pdf'
[8078]400
[9138]401    @property
402    def target_url(self):
403        is_current = self.context.__parent__.is_current
404        if not is_current:
405            return ''
406        return self.view.url(self.view.context, self.target)
407
[7591]408class CourseTicketManageActionButton(ManageActionButton):
409    grok.order(1)
410    grok.context(ICourseTicket)
411    grok.view(CourseTicketDisplayFormPage)
412    grok.require('waeup.manageStudent')
[7738]413    text = _('Manage')
[7591]414    target = 'manage'
415
416#class OnlinePaymentManageActionButton(ManageActionButton):
417#    grok.order(1)
418#    grok.context(IStudentPaymentsContainer)
419#    grok.view(PaymentsDisplayFormPage)
420#    grok.require('waeup.manageStudent')
421#    text = 'Manage payments'
422#    target = 'manage'
423
424class PaymentReceiptActionButton(ManageActionButton):
[9070]425    grok.order(9) # This button should always be the last one.
[7591]426    grok.context(IStudentOnlinePayment)
427    grok.view(OnlinePaymentDisplayFormPage)
428    grok.require('waeup.viewStudent')
429    icon = 'actionicon_pdf.png'
[8262]430    text = _('Download payment slip')
431    target = 'payment_slip.pdf'
[7591]432
433    @property
434    def target_url(self):
[8262]435        #if self.context.p_state != 'paid':
436        #    return ''
[7591]437        return self.view.url(self.view.context, self.target)
438
[8420]439class ApprovePaymentActionButton(ManageActionButton):
[9070]440    grok.order(8)
[7591]441    grok.context(IStudentOnlinePayment)
442    grok.view(OnlinePaymentDisplayFormPage)
[8420]443    grok.require('waeup.managePortal')
[8435]444    icon = 'actionicon_accept.png'
[8420]445    text = _('Approve payment')
446    target = 'approve'
[7591]447
448    @property
449    def target_url(self):
[7888]450        if self.context.p_state == 'paid':
[7591]451            return ''
452        return self.view.url(self.view.context, self.target)
453
454class AddBedTicketActionButton(ManageActionButton):
455    grok.order(1)
456    grok.context(IStudentAccommodation)
457    grok.view(AccommodationManageFormPage)
458    grok.require('waeup.handleAccommodation')
459    icon = 'actionicon_home.png'
[7738]460    text = _('Book accommodation')
[7591]461    target = 'add'
462
463class BedTicketSlipActionButton(ManageActionButton):
464    grok.order(1)
465    grok.context(IBedTicket)
466    grok.view(BedTicketDisplayFormPage)
467    grok.require('waeup.handleAccommodation')
468    icon = 'actionicon_pdf.png'
[7738]469    text = _('Download bed allocation slip')
[9452]470    target = 'bed_allocation_slip.pdf'
[7591]471
472class RelocateStudentActionButton(ManageActionButton):
473    grok.order(2)
474    grok.context(IBedTicket)
475    grok.view(BedTicketDisplayFormPage)
476    grok.require('waeup.manageHostels')
477    icon = 'actionicon_reload.png'
[7738]478    text = _('Relocate student')
[7591]479    target = 'relocate'
480
481class StudentBaseActionButton(ManageActionButton):
482    grok.order(1)
483    grok.context(IStudent)
484    grok.view(StudentBaseDisplayFormPage)
485    grok.require('waeup.handleStudent')
[7876]486    text = _('Edit')
[7591]487    target = 'edit_base'
488
489class StudentPasswordActionButton(ManageActionButton):
490    grok.order(2)
491    grok.context(IStudent)
492    grok.view(StudentBaseDisplayFormPage)
493    grok.require('waeup.handleStudent')
494    icon = 'actionicon_key.png'
[7738]495    text = _('Change password')
[7591]496    target = 'change_password'
497
498class StudentPassportActionButton(ManageActionButton):
499    grok.order(3)
500    grok.context(IStudent)
501    grok.view(StudentBaseDisplayFormPage)
502    grok.require('waeup.handleStudent')
503    icon = 'actionicon_portrait.png'
[7738]504    text = _('Change portrait')
[7591]505    target = 'change_portrait'
506
507    @property
508    def target_url(self):
[7671]509        if self.context.state != ADMITTED:
[7591]510            return ''
511        return self.view.url(self.view.context, self.target)
512
513class StudentClearanceStartActionButton(ManageActionButton):
514    grok.order(1)
515    grok.context(IStudent)
516    grok.view(StudentClearanceDisplayFormPage)
517    grok.require('waeup.handleStudent')
518    icon = 'actionicon_start.gif'
[7738]519    text = _('Start clearance')
[7591]520    target = 'start_clearance'
521
522    @property
523    def target_url(self):
[7671]524        if self.context.state != ADMITTED:
[7591]525            return ''
526        return self.view.url(self.view.context, self.target)
527
528class StudentClearanceEditActionButton(ManageActionButton):
529    grok.order(1)
530    grok.context(IStudent)
531    grok.view(StudentClearanceDisplayFormPage)
532    grok.require('waeup.handleStudent')
[7738]533    text = _('Edit')
[7591]534    target = 'cedit'
535
536    @property
537    def target_url(self):
538        if self.context.clearance_locked:
539            return ''
540        return self.view.url(self.view.context, self.target)
541
[8476]542class StartSessionActionButton(ManageActionButton):
[7591]543    grok.order(1)
544    grok.context(IStudentStudyCourse)
545    grok.view(StudyCourseDisplayFormPage)
546    grok.require('waeup.handleStudent')
547    icon = 'actionicon_start.gif'
[8920]548    text = _('Start new session')
[8471]549    target = 'start_session'
[7591]550
551    @property
552    def target_url(self):
[9138]553        if self.context.next_session_allowed and self.context.is_current:
[8471]554            return self.view.url(self.view.context, self.target)
555        return False
[7591]556
557class AddStudyLevelActionButton(AddActionButton):
558    grok.order(1)
559    grok.context(IStudentStudyCourse)
560    grok.view(StudyCourseDisplayFormPage)
561    grok.require('waeup.handleStudent')
[7738]562    text = _('Add course list')
[7591]563    target = 'add'
564
565    @property
566    def target_url(self):
[8736]567        student = self.view.context.student
[7671]568        condition1 = student.state != PAID
[7591]569        condition2 = str(student['studycourse'].current_level) in \
570            self.view.context.keys()
[9138]571        condition3 = not self.context.is_current
572        if condition1 or condition2 or condition3:
[7591]573            return ''
574        return self.view.url(self.view.context, self.target)
575
576class StudyLevelEditActionButton(ManageActionButton):
[8078]577    grok.order(2)
[7591]578    grok.context(IStudentStudyLevel)
579    grok.view(StudyLevelDisplayFormPage)
580    grok.require('waeup.handleStudent')
[8920]581    text = _('Edit course list')
[7591]582    target = 'edit'
583
584    @property
585    def target_url(self):
[8736]586        student = self.view.context.student
[9257]587        condition1 = student.state == PAID
588        condition2 = self.view.context.is_current_level
[9138]589        is_current = self.context.__parent__.is_current
[9257]590        if condition1 and condition2 and is_current:
591            return self.view.url(self.view.context, self.target)
592        return ''
[7591]593
[9517]594class AddPaymentActionButton(AddActionButton):
595    grok.order(1)
596    grok.context(IStudentPaymentsContainer)
597    grok.view(PaymentsManageFormPage)
598    grok.require('waeup.payStudent')
599    text = _('Add current session payment ticket')
600    target = 'addop'
601
602class AddPreviousPaymentActionButton(AddActionButton):
603    grok.order(2)
604    grok.context(IStudentPaymentsContainer)
605    grok.view(PaymentsManageFormPage)
606    grok.require('waeup.payStudent')
607    text = _('Add previous session payment ticket')
608    target = 'addpp'
609
610    @property
611    def target_url(self):
612        student = self.view.context.student
[9521]613        if student.before_payment:
[9517]614            return ''
615        return self.view.url(self.view.context, self.target)
616
[7184]617class StudentsTab(PrimaryNavTab):
618    """Students tab in primary navigation.
619    """
620
[7819]621    grok.context(IKofaObject)
[7184]622    grok.order(4)
[7240]623    grok.require('waeup.viewStudentsTab')
[7184]624
625    pnav = 4
[7674]626    tab_title = _(u'Students')
[7184]627
628    @property
629    def link_target(self):
630        return self.view.application_url('students')
631
[6687]632class PrimaryStudentNavManager(grok.ViewletManager):
633    """Viewlet manager for the primary navigation tab.
634    """
635    grok.name('primary_nav_student')
636
637class PrimaryStudentNavTab(grok.Viewlet):
638    """Base for primary student nav tabs.
639    """
640    grok.baseclass()
641    grok.viewletmanager(PrimaryStudentNavManager)
[7243]642    template = default_primary_nav_template
[6687]643    grok.order(1)
[7184]644    grok.require('waeup.Authenticated')
[8467]645    pnav = 0
[6687]646    tab_title = u'Some Text'
647
648    @property
649    def link_target(self):
650        return self.view.application_url()
651
652    @property
653    def active(self):
654        view_pnav = getattr(self.view, 'pnav', 0)
655        if view_pnav == self.pnav:
656            return 'active'
657        return ''
658
[7240]659class MyStudentDataTab(PrimaryStudentNavTab):
[7459]660    """MyData dropdown tab in primary navigation.
[6687]661    """
662    grok.order(3)
[7240]663    grok.require('waeup.viewMyStudentDataTab')
[7459]664    grok.template('mydatadropdowntabs')
[6687]665    pnav = 4
[7738]666    tab_title = _(u'My Data')
[6687]667
668    @property
[7459]669    def active(self):
670        view_pnav = getattr(self.view, 'pnav', 0)
671        if view_pnav == self.pnav:
672            return 'active dropdown'
673        return 'dropdown'
[7097]674
[7459]675    @property
676    def targets(self):
[9180]677        student = grok.getSite()['students'][self.request.principal.id]
678        student_url = self.view.url(student)
[9178]679        app_slip = getUtility(IExtFileStore).getFileByContext(
[9180]680            student, 'application_slip')
[7459]681        targets = []
[9178]682        if app_slip:
683            targets = [{'url':student_url + '/application_slip', 'title':'Application Slip'},]
[7459]684        targets += [
685            {'url':student_url, 'title':'Base Data'},
[8467]686            {'url':student_url + '/view_clearance',
687             'title':_('Clearance Data')},
[7738]688            {'url':student_url + '/view_personal', 'title':_('Personal Data')},
689            {'url':student_url + '/studycourse', 'title':_('Study Course')},
690            {'url':student_url + '/payments', 'title':_('Payments')},
[8467]691            {'url':student_url + '/accommodation',
692             'title':_('Accommodation Data')},
[7738]693            {'url':student_url + '/history', 'title':_('History')},
[7459]694            ]
695        return targets
696
[7107]697def handle_file_delete(context, view, download_name):
698    """Handle deletion of student file.
699
700    """
701    store = getUtility(IExtFileStore)
702    store.deleteFileByContext(context, attr=download_name)
[8735]703    context.writeLogMessage(view, 'deleted: %s' % download_name)
[7738]704    view.flash(_('${a} deleted.', mapping = {'a':download_name}))
[7107]705    return
706
[7106]707def handle_file_upload(upload, context, view, max_size, download_name=None):
708    """Handle upload of student file.
[7097]709
710    Returns `True` in case of success or `False`.
711
712    Please note that file pointer passed in (`upload`) most probably
713    points to end of file when leaving this function.
714    """
[7106]715    # Check some file requirements first
[8467]716    size = file_size(upload)
717    if size > max_size:
718        view.flash(_('Uploaded file is too big.'))
[7106]719        return False
[8467]720    upload.seek(0) # file pointer moved when determining size
721    file_format = get_fileformat(None, upload.read(512))
722    upload.seek(0) # same here
723    if file_format is None:
724        view.flash(_('Could not determine file type.'))
[7106]725        return False
726    basename, expected_ext = os.path.splitext(download_name)
[7123]727    if expected_ext:
[8467]728        if '.' + file_format != expected_ext:
[7738]729            view.flash(_('${a} file extension expected.',
[8467]730                mapping = {'a':expected_ext[1:]}))
[7123]731            return False
732    else:
[8467]733        if not file_format in ALLOWED_FILE_EXTENSIONS:
[7123]734            view.flash(
[8467]735                _('Only the following extensions are allowed: ${a}',
[7738]736                mapping = {'a':', '.join(ALLOWED_FILE_EXTENSIONS)}))
[7123]737            return False
[8467]738        download_name += '.' + file_format
[7097]739    store = getUtility(IExtFileStore)
[7106]740    file_id = IFileStoreNameChooser(context).chooseName(attr=download_name)
[7097]741    store.createFile(file_id, upload)
[8735]742    context.writeLogMessage(view, 'uploaded: %s (%s)' % (
[8467]743        download_name,upload.filename))
[7738]744    view.flash(_('File ${a} uploaded.', mapping = {'a':download_name}))
[7097]745    return True
746
747class FileManager(grok.ViewletManager):
748    """Viewlet manager for uploading files, preferably scanned images.
749    """
750    grok.name('files')
751
752class FileDisplay(grok.Viewlet):
753    """Base file display viewlet.
754    """
755    grok.baseclass()
[7993]756    grok.context(IStudent)
[7097]757    grok.viewletmanager(FileManager)
758    grok.view(StudentClearanceDisplayFormPage)
[8106]759    template = default_filedisplay_template
[7097]760    grok.order(1)
761    grok.require('waeup.viewStudent')
[7738]762    label = _(u'File')
763    title = _(u'Scan')
[7106]764    download_name = u'filename.jpg'
[7097]765
[7107]766    @property
767    def file_exists(self):
768        image = getUtility(IExtFileStore).getFileByContext(
769            self.context, attr=self.download_name)
770        if image:
771            return True
772        else:
773            return False
774
[7097]775class FileUpload(FileDisplay):
776    """Base upload viewlet.
777    """
778    grok.baseclass()
[7993]779    grok.context(IStudent)
[7097]780    grok.viewletmanager(FileManager)
781    grok.view(StudentClearanceManageFormPage)
[8106]782    template = default_fileupload_template
[7127]783    grok.require('waeup.uploadStudentFile')
[7491]784    tab_redirect = '?tab2'
[7097]785    mus = 1024 * 150
[7735]786    upload_button =_('Upload new file')
787    delete_button = _('Delete attachment')
[8135]788    show_viewlet = True
[7097]789
[7117]790    @property
791    def input_name(self):
792        return "%s" % self.__name__
793
[7097]794    def update(self):
795        self.max_upload_size = string_from_bytes(self.mus)
[7117]796        delete_button = self.request.form.get(
797            'delete_%s' % self.input_name, None)
798        upload_button = self.request.form.get(
799            'upload_%s' % self.input_name, None)
[7108]800        if delete_button:
[7107]801            handle_file_delete(
802                context=self.context, view=self.view,
803                download_name=self.download_name)
804            self.view.redirect(
[7134]805                self.view.url(
806                    self.context, self.view.__name__) + self.tab_redirect)
[7107]807            return
[7108]808        if upload_button:
809            upload = self.request.form.get(self.input_name, None)
810            if upload:
811                # We got a fresh upload
[7111]812                handle_file_upload(upload,
813                    self.context, self.view, self.mus, self.download_name)
814                self.view.redirect(
[7134]815                    self.view.url(
816                        self.context, self.view.__name__) + self.tab_redirect)
[7117]817            else:
[7738]818                self.view.flash(_('No local file selected.'))
[7117]819                self.view.redirect(
[7134]820                    self.view.url(
821                        self.context, self.view.__name__) + self.tab_redirect)
[7097]822        return
823
[7112]824class PassportDisplay(FileDisplay):
825    """Passport display viewlet.
826    """
827    grok.order(1)
828    grok.context(IStudent)
829    grok.view(StudentBaseDisplayFormPage)
830    grok.require('waeup.viewStudent')
831    grok.template('imagedisplay')
[7738]832    label = _(u'Passport Picture')
[7112]833    download_name = u'passport.jpg'
834
835class PassportUploadManage(FileUpload):
836    """Passport upload viewlet for officers.
837    """
838    grok.order(1)
839    grok.context(IStudent)
840    grok.view(StudentBaseManageFormPage)
[7136]841    grok.require('waeup.manageStudent')
[7112]842    grok.template('imageupload')
[7738]843    label = _(u'Passport Picture (jpg only)')
[7112]844    mus = 1024 * 50
845    download_name = u'passport.jpg'
[7491]846    tab_redirect = '?tab2'
[7112]847
848class PassportUploadEdit(PassportUploadManage):
849    """Passport upload viewlet for students.
850    """
[7114]851    grok.view(StudentFilesUploadPage)
[7127]852    grok.require('waeup.uploadStudentFile')
[7112]853
[7097]854class BirthCertificateDisplay(FileDisplay):
[7112]855    """Birth Certificate display viewlet.
[7097]856    """
857    grok.order(1)
[7738]858    label = _(u'Birth Certificate')
859    title = _(u'Birth Certificate Scan')
[7123]860    download_name = u'birth_certificate'
[7097]861
[7280]862class BirthCertificateSlip(BirthCertificateDisplay):
863    grok.view(ExportPDFClearanceSlipPage)
864
[7127]865class BirthCertificateUpload(FileUpload):
[7097]866    """Birth Certificate upload viewlet.
867    """
868    grok.order(1)
[7738]869    label = _(u'Birth Certificate')
870    title = _(u'Birth Certificate Scan')
[7097]871    mus = 1024 * 150
[7123]872    download_name = u'birth_certificate'
[7491]873    tab_redirect = '?tab2'
[7097]874
875class Image(grok.View):
[7351]876    """Renders images for students.
[7097]877    """
[7106]878    grok.baseclass()
[7097]879    grok.name('none.jpg')
[7993]880    grok.context(IStudent)
[7097]881    grok.require('waeup.viewStudent')
[7106]882    download_name = u'none.jpg'
[7097]883
884    def render(self):
885        # A filename chooser turns a context into a filename suitable
886        # for file storage.
887        image = getUtility(IExtFileStore).getFileByContext(
[7106]888            self.context, attr=self.download_name)
[7097]889        if image is None:
890            # show placeholder image
[7123]891            self.response.setHeader('Content-Type', 'image/jpeg')
[7097]892            return open(DEFAULT_IMAGE_PATH, 'rb').read()
[7123]893        dummy,ext = os.path.splitext(image.name)
894        if ext == '.jpg':
895            self.response.setHeader('Content-Type', 'image/jpeg')
896        elif ext == '.png':
897            self.response.setHeader('Content-Type', 'image/png')
898        elif ext == '.pdf':
899            self.response.setHeader('Content-Type', 'application/pdf')
900        elif ext == '.tif':
901            self.response.setHeader('Content-Type', 'image/tiff')
[7097]902        return image
903
[7112]904class Passport(Image):
905    """Renders jpeg passport picture.
906    """
907    grok.name('passport.jpg')
908    download_name = u'passport.jpg'
909    grok.context(IStudent)
910
[7351]911class ApplicationSlipImage(Image):
912    """Renders application slip scan.
913    """
914    grok.name('application_slip')
915    download_name = u'application_slip'
916
[7097]917class BirthCertificateImage(Image):
[7351]918    """Renders birth certificate scan.
[7097]919    """
[7123]920    grok.name('birth_certificate')
921    download_name = u'birth_certificate'
Note: See TracBrowser for help on using the repository browser.