source: main/waeup.kofa/trunk/src/waeup/kofa/students/interfaces.py @ 9554

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

Add timestamp to personal data. This timestamp will be checked when students log in. Students sould be remembered to frequently update their personal data.

  • Property svn:keywords set to Id
File size: 18.8 KB
Line 
1## $Id: interfaces.py 9543 2012-11-05 18:03:39Z 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#from datetime import datetime
19from zope.component import getUtility
20from zope.interface import Attribute, Interface
21from zope import schema
22from zc.sourcefactory.contextual import BasicContextualSourceFactory
23from waeup.kofa.browser.interfaces import IStudentNavigationBase
24from waeup.kofa.interfaces import (
25    IKofaObject, academic_sessions_vocab, validate_email, ICSVExporter)
26from waeup.kofa.interfaces import MessageFactory as _
27from waeup.kofa.schema import TextLineChoice, FormattedDate, PhoneNumber
28from waeup.kofa.students.vocabularies import (
29    StudyLevelSource, contextual_reg_num_source, contextual_mat_num_source,
30    GenderSource, nats_vocab
31    )
32from waeup.kofa.payments.interfaces import (
33    IPaymentsContainer, IOnlinePayment)
34from waeup.kofa.university.vocabularies import (
35    CourseSource, StudyModeSource, CertificateSource, SemesterSource)
36
37# VerdictSource can't be placed into the vocabularies module because it
38# requires importing IStudentsUtils which then leads to circular imports.
39class VerdictSource(BasicContextualSourceFactory):
40    """A verdicts source delivers all verdicts provided
41    in the portal.
42    """
43    def getValues(self, context):
44        verdicts_dict = getUtility(IStudentsUtils).VERDICTS_DICT
45        return sorted(verdicts_dict.keys())
46
47    def getToken(self, context, value):
48        return value
49
50    def getTitle(self, context, value):
51        verdicts_dict = getUtility(IStudentsUtils).VERDICTS_DICT
52        if value != '0':
53            return verdicts_dict[value] + ' (%s)' % value
54        return verdicts_dict[value]
55
56
57class IStudentsUtils(Interface):
58    """A collection of methods which are subject to customization.
59
60    """
61    def setReturningData(student):
62        """ This method defines what happens after school fee payment
63        depending on the student's senate verdict.
64
65        In the base configuration current level is always increased
66        by 100 no matter which verdict has been assigned.
67        """
68
69    def setPaymentDetails(category, student, previous_session=None,
70            previous_level=None,):
71        """Create Payment object and set the payment data of a student for
72        the payment category specified.
73
74        """
75
76    def getAccommodation_details(student):
77        """Determine the accommodation dates of a student.
78
79        """
80
81    def selectBed(available_beds):
82        """Select a bed from a list of available beds.
83
84        In the standard configuration we select the first bed found,
85        but can also randomize the selection if we like.
86        """
87
88    def renderPDF(view, subject='', filename='slip.pdf',):
89        """Render pdf slips for various pages.
90
91        """
92
93class IStudentsContainer(IKofaObject):
94    """A students container contains university students.
95
96    """
97    def addStudent(student):
98        """Add an IStudent object and subcontainers.
99
100        """
101
102    def archive(id=None):
103        """Create on-dist archive of students.
104
105        If id is `None`, all students are archived.
106
107        If id contains a single id string, only the respective
108        students are archived.
109
110        If id contains a list of id strings all of the respective
111        students types are saved to disk.
112        """
113
114    def clear(id=None, archive=True):
115        """Remove students of type given by 'id'.
116
117        Optionally archive the students.
118
119        If id is `None`, all students are archived.
120
121        If id contains a single id string, only the respective
122        students are archived.
123
124        If id contains a list of id strings all of the respective
125        student types are saved to disk.
126
127        If `archive` is ``False`` none of the archive-handling is done
128        and respective students are simply removed from the
129        database.
130        """
131
132    unique_student_id = Attribute("""A unique student id.""")
133
134class IStudentNavigation(IStudentNavigationBase):
135    """Interface needed for student navigation, logging, etc.
136
137    """
138    student = Attribute('Student object of context.')
139
140    def writeLogMessage(view, message):
141        """Write a view specific log message into students.log.
142
143        """
144
145class IStudentBase(IKofaObject):
146    """Representation of student base data.
147
148    """
149    history = Attribute('Object history, a list of messages')
150    state = Attribute('Returns the registration state of a student')
151    password = Attribute('Encrypted password of a student')
152    temp_password = Attribute(
153        'Dictionary with user name, timestamp and encrypted password')
154    certcode = Attribute('The certificate code of any chosen study course')
155    depcode = Attribute('The department code of any chosen study course')
156    faccode = Attribute('The faculty code of any chosen study course')
157    current_session = Attribute('The current session of the student')
158    current_level = Attribute('The current level of the student')
159    current_mode = Attribute('The current mode of the student')
160    current_verdict = Attribute('The current verdict of the student')
161    fullname = Attribute('All name parts separated by hyphens')
162    display_fullname = Attribute('The fullname of an applicant')
163    is_postgrad = Attribute('True if postgraduate student')
164
165    suspended = schema.Bool(
166        title = _(u'Account suspended'),
167        default = False,
168        required = False,
169        )
170
171    student_id = schema.TextLine(
172        title = _(u'Student Id'),
173        required = False,
174        )
175
176    firstname = schema.TextLine(
177        title = _(u'First Name'),
178        required = True,
179        )
180
181    middlename = schema.TextLine(
182        title = _(u'Middle Name'),
183        required = False,
184        )
185
186    lastname = schema.TextLine(
187        title = _(u'Last Name (Surname)'),
188        required = True,
189        )
190
191    sex = schema.Choice(
192        title = _(u'Sex'),
193        source = GenderSource(),
194        required = True,
195        )
196
197    reg_number = TextLineChoice(
198        title = _(u'Registration Number'),
199        required = True,
200        readonly = False,
201        source = contextual_reg_num_source,
202        )
203
204    matric_number = TextLineChoice(
205        title = _(u'Matriculation Number'),
206        required = False,
207        readonly = False,
208        source = contextual_mat_num_source,
209        )
210
211    adm_code = schema.TextLine(
212        title = _(u'PWD Activation Code'),
213        required = False,
214        readonly = False,
215        )
216
217    email = schema.ASCIILine(
218        title = _(u'Email'),
219        required = False,
220        constraint=validate_email,
221        )
222    phone = PhoneNumber(
223        title = _(u'Phone'),
224        description = u'',
225        required = False,
226        )
227
228    def setTempPassword(user, password):
229        """Set a temporary password (LDAP-compatible) SSHA encoded for
230        officers.
231
232        """
233
234    def getTempPassword():
235        """Check if a temporary password has been set and if it
236        is not expired.
237
238        Return the temporary password if valid,
239        None otherwise. Unset the temporary password if expired.
240        """
241
242    def transfer(certificate, current_session,
243        current_level, current_verdict):
244        """ Creates a new studycourse and backups the old one.
245
246        """
247
248class IUGStudentClearance(IKofaObject):
249    """Representation of undergraduate student clearance data.
250
251    """
252    officer_comment = schema.Text(
253        title = _(u"Officer's Comment"),
254        required = False,
255        )
256
257    clearance_locked = schema.Bool(
258        title = _(u'Clearance form locked'),
259        default = False,
260        required = False,
261        )
262
263    clr_code = schema.TextLine(
264        title = _(u'CLR Activation Code'),
265        required = False,
266        readonly = False,
267        )
268
269    date_of_birth = FormattedDate(
270        title = _(u'Date of Birth'),
271        required = True,
272        show_year = True,
273        )
274
275    nationality = schema.Choice(
276        vocabulary = nats_vocab,
277        title = _(u'Nationality'),
278        required = False,
279        )
280
281class IPGStudentClearance(IUGStudentClearance):
282    """Representation of postgraduate student clearance data.
283
284    """
285    employer = schema.TextLine(
286        title = _(u'Employer'),
287        required = False,
288        readonly = False,
289        )
290
291class IStudentPersonal(IKofaObject):
292    """Representation of student personal data.
293
294    """
295    personal_updated = schema.Datetime(
296        title = _(u'Updated'),
297        required = False,
298        readonly = False,
299        )
300
301    perm_address = schema.Text(
302        title = _(u'Permanent Address'),
303        required = False,
304        )
305
306class IStudent(IStudentBase,IUGStudentClearance,IPGStudentClearance,
307    IStudentPersonal):
308    """Representation of a student.
309
310    """
311
312class IStudentUpdateByRegNo(IStudent):
313    """Representation of a student. Skip regular reg_number validation.
314
315    """
316    reg_number = schema.TextLine(
317        title = _(u'Registration Number'),
318        required = False,
319        )
320
321class IStudentUpdateByMatricNo(IStudent):
322    """Representation of a student. Skip regular matric_number validation.
323
324    """
325    matric_number = schema.TextLine(
326        title = _(u'Matriculation Number'),
327        required = False,
328        )
329
330class IStudentRequestPW(IStudent):
331    """Representation of an student for first-time password request.
332
333    This interface is used when students use the requestpw page to
334    login for the the first time.
335    """
336    number = schema.TextLine(
337        title = _(u'Registr. or Matric. Number'),
338        required = True,
339        )
340
341    firstname = schema.TextLine(
342        title = _(u'First Name'),
343        required = True,
344        )
345
346    email = schema.ASCIILine(
347        title = _(u'Email Address'),
348        required = True,
349        constraint=validate_email,
350        )
351
352class IStudentStudyCourse(IKofaObject):
353    """A container for student study levels.
354
355    """
356    certificate = schema.Choice(
357        title = _(u'Certificate'),
358        source = CertificateSource(),
359        required = False,
360        )
361
362    entry_mode = schema.Choice(
363        title = _(u'Entry Mode'),
364        source = StudyModeSource(),
365        required = True,
366        readonly = False,
367        )
368
369    entry_session = schema.Choice(
370        title = _(u'Entry Session'),
371        source = academic_sessions_vocab,
372        #default = datetime.now().year,
373        required = True,
374        readonly = False,
375        )
376
377    current_session = schema.Choice(
378        title = _(u'Current Session'),
379        source = academic_sessions_vocab,
380        required = True,
381        readonly = False,
382        )
383
384    current_level = schema.Choice(
385        title = _(u'Current Level'),
386        source = StudyLevelSource(),
387        required = False,
388        readonly = False,
389        )
390
391    current_verdict = schema.Choice(
392        title = _(u'Current Verdict'),
393        source = VerdictSource(),
394        default = '0',
395        required = False,
396        )
397
398    previous_verdict = schema.Choice(
399        title = _(u'Previous Verdict'),
400        source = VerdictSource(),
401        default = '0',
402        required = False,
403        )
404
405class IStudentStudyCourseTransfer(IStudentStudyCourse):
406    """An student transfers.
407
408    """
409
410    certificate = schema.Choice(
411        title = _(u'Certificate'),
412        source = CertificateSource(),
413        required = True,
414        )
415
416    current_level = schema.Choice(
417        title = _(u'Current Level'),
418        source = StudyLevelSource(),
419        required = True,
420        readonly = False,
421        )
422
423
424IStudentStudyCourseTransfer['certificate'].order = IStudentStudyCourse[
425    'certificate'].order
426IStudentStudyCourseTransfer['current_level'].order = IStudentStudyCourse[
427    'current_level'].order
428
429class IStudentVerdictUpdate(IKofaObject):
430    """A interface for verdict imports.
431
432    """
433
434    current_verdict = schema.Choice(
435        title = _(u'Current Verdict'),
436        source = VerdictSource(),
437        required = True,
438        )
439
440    current_session = schema.Choice(
441        title = _(u'Current Session'),
442        source = academic_sessions_vocab,
443        required = True,
444        )
445
446    current_level = schema.Choice(
447        title = _(u'Current Level'),
448        source = StudyLevelSource(),
449        required = True,
450        )
451
452    bypass_validation = schema.Bool(
453        title = _(u'Bypass validation'),
454        required = False,
455        )
456
457    validated_by = schema.TextLine(
458        title = _(u'Validated by'),
459        required = False,
460        )
461
462class IStudentStudyLevel(IKofaObject):
463    """A container for course tickets.
464
465    """
466    level = Attribute('The level code')
467    number_of_tickets = Attribute('Number of tickets contained in this level')
468    certcode = Attribute('The certificate code of the study course')
469    is_current_level = Attribute('Is this level the current level of the student?')
470    total_credits = Attribute('Total of all ticket credits in this study level.')
471
472    level_session = schema.Choice(
473        title = _(u'Session'),
474        source = academic_sessions_vocab,
475        required = True,
476        )
477
478    level_verdict = schema.Choice(
479        title = _(u'Verdict'),
480        source = VerdictSource(),
481        default = '0',
482        required = False,
483        )
484
485    validated_by = schema.TextLine(
486        title = _(u'Validated by'),
487        default = None,
488        required = False,
489        )
490
491    validation_date = schema.Datetime(
492        title = _(u'Validation Date'),
493        required = False,
494        readonly = False,
495        )
496
497    def addCourseTicket(ticket, course):
498        """Add a course ticket object.
499        """
500
501    def addCertCourseTickets(cert):
502        """Collect all certificate courses and create course
503        tickets automatically.
504        """
505
506class ICourseTicket(IKofaObject):
507    """An interface for course tickets.
508
509    """
510    code = Attribute('code of the original course')
511    certcode = Attribute('certificate code of the study course')
512
513    title = schema.TextLine(
514        title = _(u'Title'),
515        required = False,
516        )
517
518    fcode = schema.TextLine(
519        title = _(u'Faculty Code'),
520        required = False,
521        )
522
523    dcode = schema.TextLine(
524        title = _(u'Department Code'),
525        required = False,
526        )
527
528    semester = schema.Choice(
529        title = _(u'Semester/Term'),
530        source = SemesterSource(),
531        required = False,
532        )
533
534    passmark = schema.Int(
535        title = _(u'Passmark'),
536        required = False,
537        )
538
539    credits = schema.Int(
540        title = _(u'Credits'),
541        required = False,
542        )
543
544    mandatory = schema.Bool(
545        title = _(u'Required'),
546        default = False,
547        required = False,
548        )
549
550    score = schema.Int(
551        title = _(u'Score'),
552        default = 0,
553        required = False,
554        )
555
556    carry_over = schema.Bool(
557        title = _(u'Carry-over Course'),
558        default = False,
559        required = False,
560        )
561
562    automatic = schema.Bool(
563        title = _(u'Automatical Creation'),
564        default = False,
565        required = False,
566        )
567
568
569    def getLevel():
570        """Returns the id of the level the ticket has been added to.
571        """
572
573    def getLevelSession():
574        """Returns the session of the level the ticket has been added to.
575        """
576
577class ICourseTicketAdd(IKofaObject):
578    """An interface for adding course tickets.
579
580    """
581    course = schema.Choice(
582        title = _(u'Course'),
583        source = CourseSource(),
584        readonly = False,
585        )
586
587class ICourseTicketImport(ICourseTicket):
588    """An interface for importing course results and nothing more.
589
590    """
591    score = schema.Int(
592        title = _(u'Score'),
593        required = False,
594        readonly = False,
595        )
596
597    level_session = schema.Choice(
598        title = _(u'Level Session'),
599        source = academic_sessions_vocab,
600        required = False,
601        readonly = False,
602        )
603
604class IStudentAccommodation(IKofaObject):
605    """A container for student accommodation objects.
606
607    """
608
609    def addBedTicket(bedticket):
610        """Add a bed ticket object.
611        """
612
613
614class IBedTicket(IKofaObject):
615    """A ticket for accommodation booking.
616
617    """
618    bed = Attribute('The bed object.')
619
620    bed_coordinates = schema.TextLine(
621        title = _(u'Allocated Bed'),
622        required = True,
623        readonly = False,
624        )
625
626    bed_type = schema.TextLine(
627        title = _(u'Requested Bed Type'),
628        required = True,
629        readonly = False,
630        )
631
632    booking_session = schema.Choice(
633        title = _(u'Session'),
634        source = academic_sessions_vocab,
635        required = True,
636        readonly = True,
637        )
638
639    booking_date = schema.Datetime(
640        title = _(u'Booking Date'),
641        required = False,
642        readonly = True,
643        )
644
645    booking_code = schema.TextLine(
646        title = _(u'Booking Activation Code'),
647        required = False,
648        readonly = True,
649        )
650
651    def getSessionString():
652        """Returns the title of academic_sessions_vocab term.
653
654        """
655
656class IStudentPaymentsContainer(IPaymentsContainer):
657    """A container for student payment objects.
658
659    """
660
661class IStudentOnlinePayment(IOnlinePayment):
662    """A student payment via payment gateways.
663
664    """
665
666    p_current = schema.Bool(
667        title = _(u'Current Session Payment'),
668        default = True,
669        required = False,
670        )
671
672    p_level = schema.Int(
673        title = _(u'Payment Level'),
674        required = False,
675        )
676
677    def doAfterStudentPayment():
678        """Process student after payment was made.
679
680        """
681
682    def doAfterStudentPaymentApproval():
683        """Process student after payment was approved.
684
685        """
686
687    def approveStudentPayment():
688        """Approve payment and process student.
689
690        """
691
692IStudentOnlinePayment['p_level'].order = IStudentOnlinePayment[
693    'p_session'].order
694
695class IStudentPreviousPayment(IOnlinePayment):
696    """An interface for adding previous session payments.
697
698    """
699
700    p_session = schema.Choice(
701        title = _(u'Payment Session'),
702        source = academic_sessions_vocab,
703        required = True,
704        )
705
706    p_level = schema.Choice(
707        title = _(u'Payment Level'),
708        source = StudyLevelSource(),
709        required = True,
710        )
711
712class ICSVStudentExporter(ICSVExporter):
713    """A regular ICSVExporter that additionally supports exporting
714      data from a given student object.
715    """
716
717    def export_student(student, filepath=None):
718        """Export data for a given student.
719        """
Note: See TracBrowser for help on using the repository browser.