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

Last change on this file since 10447 was 10447, checked in by Henrik Bettermann, 11 years ago

Add Interface for transcript address.

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