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

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

Use new attrs_to_fields function to display gpa and total_credits on level pages.

  • Property svn:keywords set to Id
File size: 19.4 KB
Line 
1## $Id: interfaces.py 9690 2012-11-20 06:17:36Z 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 IStudentPersonalEdit(IStudentPersonal):
313    """Interface for editing personal data by students.
314
315    Here we can repeat the fields from IStudentPersonal and set the
316    `required` if necessary.
317    """
318
319    perm_address = schema.Text(
320        title = _(u'Permanent Address'),
321        required = True,
322        )
323
324class IStudentUpdateByRegNo(IStudent):
325    """Representation of a student. Skip regular reg_number validation.
326
327    """
328    reg_number = schema.TextLine(
329        title = _(u'Registration Number'),
330        required = False,
331        )
332
333class IStudentUpdateByMatricNo(IStudent):
334    """Representation of a student. Skip regular matric_number validation.
335
336    """
337    matric_number = schema.TextLine(
338        title = _(u'Matriculation Number'),
339        required = False,
340        )
341
342class IStudentRequestPW(IStudent):
343    """Representation of an student for first-time password request.
344
345    This interface is used when students use the requestpw page to
346    login for the the first time.
347    """
348    number = schema.TextLine(
349        title = _(u'Registr. or Matric. Number'),
350        required = True,
351        )
352
353    firstname = schema.TextLine(
354        title = _(u'First Name'),
355        required = True,
356        )
357
358    email = schema.ASCIILine(
359        title = _(u'Email Address'),
360        required = True,
361        constraint=validate_email,
362        )
363
364class IStudentStudyCourse(IKofaObject):
365    """A container for student study levels.
366
367    """
368    certificate = schema.Choice(
369        title = _(u'Certificate'),
370        source = CertificateSource(),
371        required = False,
372        )
373
374    entry_mode = schema.Choice(
375        title = _(u'Entry Mode'),
376        source = StudyModeSource(),
377        required = True,
378        readonly = False,
379        )
380
381    entry_session = schema.Choice(
382        title = _(u'Entry Session'),
383        source = academic_sessions_vocab,
384        #default = datetime.now().year,
385        required = True,
386        readonly = False,
387        )
388
389    current_session = schema.Choice(
390        title = _(u'Current Session'),
391        source = academic_sessions_vocab,
392        required = True,
393        readonly = False,
394        )
395
396    current_level = schema.Choice(
397        title = _(u'Current Level'),
398        source = StudyLevelSource(),
399        required = False,
400        readonly = False,
401        )
402
403    current_verdict = schema.Choice(
404        title = _(u'Current Verdict'),
405        source = VerdictSource(),
406        default = '0',
407        required = False,
408        )
409
410    previous_verdict = schema.Choice(
411        title = _(u'Previous Verdict'),
412        source = VerdictSource(),
413        default = '0',
414        required = False,
415        )
416
417class IStudentStudyCourseTransfer(IStudentStudyCourse):
418    """An student transfers.
419
420    """
421
422    certificate = schema.Choice(
423        title = _(u'Certificate'),
424        source = CertificateSource(),
425        required = True,
426        )
427
428    current_level = schema.Choice(
429        title = _(u'Current Level'),
430        source = StudyLevelSource(),
431        required = True,
432        readonly = False,
433        )
434
435
436IStudentStudyCourseTransfer['certificate'].order = IStudentStudyCourse[
437    'certificate'].order
438IStudentStudyCourseTransfer['current_level'].order = IStudentStudyCourse[
439    'current_level'].order
440
441class IStudentVerdictUpdate(IKofaObject):
442    """A interface for verdict imports.
443
444    """
445
446    current_verdict = schema.Choice(
447        title = _(u'Current Verdict'),
448        source = VerdictSource(),
449        required = True,
450        )
451
452    current_session = schema.Choice(
453        title = _(u'Current Session'),
454        source = academic_sessions_vocab,
455        required = True,
456        )
457
458    current_level = schema.Choice(
459        title = _(u'Current Level'),
460        source = StudyLevelSource(),
461        required = True,
462        )
463
464    bypass_validation = schema.Bool(
465        title = _(u'Bypass validation'),
466        required = False,
467        )
468
469    validated_by = schema.TextLine(
470        title = _(u'Validated by'),
471        required = False,
472        )
473
474class IStudentStudyLevel(IKofaObject):
475    """A container for course tickets.
476
477    """
478    level = Attribute('The level code')
479    number_of_tickets = Attribute('Number of tickets contained in this level')
480    certcode = Attribute('The certificate code of the study course')
481    is_current_level = Attribute('Is this level the current level of the student?')
482
483    level_session = schema.Choice(
484        title = _(u'Session'),
485        source = academic_sessions_vocab,
486        required = True,
487        )
488
489    level_verdict = schema.Choice(
490        title = _(u'Verdict'),
491        source = VerdictSource(),
492        default = '0',
493        required = False,
494        )
495
496    validated_by = schema.TextLine(
497        title = _(u'Validated by'),
498        default = None,
499        required = False,
500        )
501
502    validation_date = schema.Datetime(
503        title = _(u'Validation Date'),
504        required = False,
505        readonly = False,
506        )
507
508    total_credits = schema.Int(
509        title = _(u'Total Credits'),
510        required = False,
511        readonly = True,
512        )
513
514    gpa = schema.Int(
515        title = _(u'GPA'),
516        required = False,
517        readonly = True,
518        )
519
520    def addCourseTicket(ticket, course):
521        """Add a course ticket object.
522        """
523
524    def addCertCourseTickets(cert):
525        """Collect all certificate courses and create course
526        tickets automatically.
527        """
528
529class ICourseTicket(IKofaObject):
530    """An interface for course tickets.
531
532    """
533    code = Attribute('code of the original course')
534    certcode = Attribute('certificate code of the study course')
535    grade = Attribute('grade calculated from score')
536    weight = Attribute('weight calculated from score')
537
538    title = schema.TextLine(
539        title = _(u'Title'),
540        required = False,
541        )
542
543    fcode = schema.TextLine(
544        title = _(u'Faculty Code'),
545        required = False,
546        )
547
548    dcode = schema.TextLine(
549        title = _(u'Department Code'),
550        required = False,
551        )
552
553    semester = schema.Choice(
554        title = _(u'Semester/Term'),
555        source = SemesterSource(),
556        required = False,
557        )
558
559    passmark = schema.Int(
560        title = _(u'Passmark'),
561        required = False,
562        )
563
564    credits = schema.Int(
565        title = _(u'Credits'),
566        required = False,
567        )
568
569    mandatory = schema.Bool(
570        title = _(u'Required'),
571        default = False,
572        required = False,
573        )
574
575    score = schema.Int(
576        title = _(u'Score'),
577        default = None,
578        required = False,
579        )
580
581    carry_over = schema.Bool(
582        title = _(u'Carry-over Course'),
583        default = False,
584        required = False,
585        )
586
587    automatic = schema.Bool(
588        title = _(u'Automatical Creation'),
589        default = False,
590        required = False,
591        )
592
593    def getLevel():
594        """Returns the id of the level the ticket has been added to.
595        """
596
597    def getLevelSession():
598        """Returns the session of the level the ticket has been added to.
599        """
600
601class ICourseTicketAdd(IKofaObject):
602    """An interface for adding course tickets.
603
604    """
605    course = schema.Choice(
606        title = _(u'Course'),
607        source = CourseSource(),
608        readonly = False,
609        )
610
611class ICourseTicketImport(ICourseTicket):
612    """An interface for importing course results and nothing more.
613
614    """
615    score = schema.Int(
616        title = _(u'Score'),
617        required = False,
618        readonly = False,
619        )
620
621    level_session = schema.Choice(
622        title = _(u'Level Session'),
623        source = academic_sessions_vocab,
624        required = False,
625        readonly = False,
626        )
627
628class IStudentAccommodation(IKofaObject):
629    """A container for student accommodation objects.
630
631    """
632
633    def addBedTicket(bedticket):
634        """Add a bed ticket object.
635        """
636
637
638class IBedTicket(IKofaObject):
639    """A ticket for accommodation booking.
640
641    """
642    bed = Attribute('The bed object.')
643
644    bed_coordinates = schema.TextLine(
645        title = _(u'Allocated Bed'),
646        required = True,
647        readonly = False,
648        )
649
650    bed_type = schema.TextLine(
651        title = _(u'Requested Bed Type'),
652        required = True,
653        readonly = False,
654        )
655
656    booking_session = schema.Choice(
657        title = _(u'Session'),
658        source = academic_sessions_vocab,
659        required = True,
660        readonly = True,
661        )
662
663    booking_date = schema.Datetime(
664        title = _(u'Booking Date'),
665        required = False,
666        readonly = True,
667        )
668
669    booking_code = schema.TextLine(
670        title = _(u'Booking Activation Code'),
671        required = False,
672        readonly = True,
673        )
674
675    def getSessionString():
676        """Returns the title of academic_sessions_vocab term.
677
678        """
679
680class IStudentPaymentsContainer(IPaymentsContainer):
681    """A container for student payment objects.
682
683    """
684
685class IStudentOnlinePayment(IOnlinePayment):
686    """A student payment via payment gateways.
687
688    """
689
690    p_current = schema.Bool(
691        title = _(u'Current Session Payment'),
692        default = True,
693        required = False,
694        )
695
696    p_level = schema.Int(
697        title = _(u'Payment Level'),
698        required = False,
699        )
700
701    def doAfterStudentPayment():
702        """Process student after payment was made.
703
704        """
705
706    def doAfterStudentPaymentApproval():
707        """Process student after payment was approved.
708
709        """
710
711    def approveStudentPayment():
712        """Approve payment and process student.
713
714        """
715
716IStudentOnlinePayment['p_level'].order = IStudentOnlinePayment[
717    'p_session'].order
718
719class IStudentPreviousPayment(IOnlinePayment):
720    """An interface for adding previous session payments.
721
722    """
723
724    p_session = schema.Choice(
725        title = _(u'Payment Session'),
726        source = academic_sessions_vocab,
727        required = True,
728        )
729
730    p_level = schema.Choice(
731        title = _(u'Payment Level'),
732        source = StudyLevelSource(),
733        required = True,
734        )
735
736class ICSVStudentExporter(ICSVExporter):
737    """A regular ICSVExporter that additionally supports exporting
738      data from a given student object.
739    """
740
741    def export_student(student, filepath=None):
742        """Export data for a given student.
743        """
Note: See TracBrowser for help on using the repository browser.