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

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

Derive information about passed and failed course.

  • Property svn:keywords set to Id
File size: 22.6 KB
Line 
1## $Id: interfaces.py 10553 2013-08-29 05:24:10Z 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    transcript_comment = schema.Text(
339        title = _(u'Comment'),
340        required = False,
341        )
342
343
344class IStudent(IStudentBase,IUGStudentClearance,IPGStudentClearance,
345    IStudentPersonal, IStudentTranscript):
346    """Representation of a student.
347
348    """
349
350class IStudentPersonalEdit(IStudentPersonal):
351    """Interface for editing personal data by students.
352
353    Here we can repeat the fields from IStudentPersonal and set the
354    `required` if necessary.
355    """
356
357    perm_address = schema.Text(
358        title = _(u'Permanent Address'),
359        required = True,
360        )
361
362class IStudentUpdateByRegNo(IStudent):
363    """Representation of a student. Skip regular reg_number validation.
364
365    """
366    reg_number = schema.TextLine(
367        title = _(u'Registration Number'),
368        required = False,
369        )
370
371class IStudentUpdateByMatricNo(IStudent):
372    """Representation of a student. Skip regular matric_number validation.
373
374    """
375    matric_number = schema.TextLine(
376        title = _(u'Matriculation Number'),
377        required = False,
378        )
379
380class IStudentRequestPW(IStudent):
381    """Representation of an student for first-time password request.
382
383    This interface is used when students use the requestpw page to
384    login for the the first time.
385    """
386    number = schema.TextLine(
387        title = _(u'Registr. or Matric. Number'),
388        required = True,
389        )
390
391    firstname = schema.TextLine(
392        title = _(u'First Name'),
393        required = True,
394        )
395
396    email = schema.ASCIILine(
397        title = _(u'Email Address'),
398        required = True,
399        constraint=validate_email,
400        )
401
402class IStudentStudyCourse(IKofaObject):
403    """A container for student study levels.
404
405    """
406    certificate = schema.Choice(
407        title = _(u'Certificate'),
408        source = CertificateSource(),
409        required = False,
410        )
411
412    entry_mode = schema.Choice(
413        title = _(u'Entry Mode'),
414        source = StudyModeSource(),
415        required = True,
416        readonly = False,
417        )
418
419    entry_session = schema.Choice(
420        title = _(u'Entry Session'),
421        source = academic_sessions_vocab,
422        #default = datetime.now().year,
423        required = True,
424        readonly = False,
425        )
426
427    current_session = schema.Choice(
428        title = _(u'Current Session'),
429        source = academic_sessions_vocab,
430        required = True,
431        readonly = False,
432        )
433
434    current_level = schema.Choice(
435        title = _(u'Current Level'),
436        source = StudyLevelSource(),
437        required = False,
438        readonly = False,
439        )
440
441    current_verdict = schema.Choice(
442        title = _(u'Current Verdict'),
443        source = VerdictSource(),
444        default = '0',
445        required = False,
446        )
447
448    previous_verdict = schema.Choice(
449        title = _(u'Previous Verdict'),
450        source = VerdictSource(),
451        default = '0',
452        required = False,
453        )
454
455class IStudentStudyCourseTransfer(IStudentStudyCourse):
456    """An student transfers.
457
458    """
459
460    certificate = schema.Choice(
461        title = _(u'Certificate'),
462        source = CertificateSource(),
463        required = True,
464        )
465
466    current_level = schema.Choice(
467        title = _(u'Current Level'),
468        source = StudyLevelSource(),
469        required = True,
470        readonly = False,
471        )
472
473    entry_session = schema.Choice(
474        title = _(u'Entry Session'),
475        source = academic_sessions_vocab,
476        #default = datetime.now().year,
477        required = False,
478        readonly = False,
479        )
480
481
482IStudentStudyCourseTransfer['certificate'].order = IStudentStudyCourse[
483    'certificate'].order
484IStudentStudyCourseTransfer['current_level'].order = IStudentStudyCourse[
485    'current_level'].order
486
487class IStudentStudyCourseTranscript(IKofaObject):
488    """An interface for student transcripts.
489
490    """
491
492    entry_mode = schema.Choice(
493        title = _(u'Entry Mode'),
494        source = StudyModeSource(),
495        required = True,
496        readonly = False,
497        )
498
499    entry_session = schema.Choice(
500        title = _(u'Entry Session'),
501        source = academic_sessions_vocab,
502        #default = datetime.now().year,
503        required = True,
504        readonly = False,
505        )
506
507class IStudentVerdictUpdate(IKofaObject):
508    """A interface for verdict imports.
509
510    """
511
512    current_verdict = schema.Choice(
513        title = _(u'Current Verdict'),
514        source = VerdictSource(),
515        required = True,
516        )
517
518    current_session = schema.Choice(
519        title = _(u'Current Session'),
520        source = academic_sessions_vocab,
521        required = True,
522        )
523
524    current_level = schema.Choice(
525        title = _(u'Current Level'),
526        source = StudyLevelSource(),
527        required = True,
528        )
529
530    bypass_validation = schema.Bool(
531        title = _(u'Bypass validation'),
532        required = False,
533        )
534
535    validated_by = schema.TextLine(
536        title = _(u'Validated by'),
537        required = False,
538        )
539
540class IStudentStudyLevel(IKofaObject):
541    """A container for course tickets.
542
543    """
544    level = Attribute('The level code')
545    number_of_tickets = Attribute('Number of tickets contained in this level')
546    certcode = Attribute('The certificate code of the study course')
547    is_current_level = Attribute('Is this level the current level of the student?')
548    passed_params = Attribute('Information about passed and failed courses')
549
550    level_session = schema.Choice(
551        title = _(u'Session'),
552        source = academic_sessions_vocab,
553        required = True,
554        )
555
556    level_verdict = schema.Choice(
557        title = _(u'Verdict'),
558        source = VerdictSource(),
559        default = '0',
560        required = False,
561        )
562
563    validated_by = schema.TextLine(
564        title = _(u'Validated by'),
565        default = None,
566        required = False,
567        )
568
569    validation_date = schema.Datetime(
570        title = _(u'Validation Date'),
571        required = False,
572        readonly = False,
573        )
574
575    total_credits = schema.Int(
576        title = _(u'Total Credits'),
577        required = False,
578        readonly = True,
579        )
580
581    gpa = schema.Int(
582        title = _(u'Unrectified GPA'),
583        required = False,
584        readonly = True,
585        )
586
587    def addCourseTicket(ticket, course):
588        """Add a course ticket object.
589        """
590
591    def addCertCourseTickets(cert):
592        """Collect all certificate courses and create course
593        tickets automatically.
594        """
595
596class ICourseTicket(IKofaObject):
597    """An interface for course tickets.
598
599    """
600    code = Attribute('code of the original course')
601    certcode = Attribute('certificate code of the study course')
602    grade = Attribute('grade calculated from score')
603    weight = Attribute('weight calculated from score')
604    removable_by_student = Attribute('Is student allowed to remove the ticket?')
605    level_session = Attribute('session of the level the ticket has been added to')
606    level = Attribute('id of the level the ticket has been added to')
607
608    title = schema.TextLine(
609        title = _(u'Title'),
610        required = False,
611        )
612
613    fcode = schema.TextLine(
614        title = _(u'Faculty Code'),
615        required = False,
616        )
617
618    dcode = schema.TextLine(
619        title = _(u'Department Code'),
620        required = False,
621        )
622
623    semester = schema.Choice(
624        title = _(u'Semester/Term'),
625        source = SemesterSource(),
626        required = False,
627        )
628
629    passmark = schema.Int(
630        title = _(u'Passmark'),
631        required = False,
632        )
633
634    credits = schema.Int(
635        title = _(u'Credits'),
636        required = False,
637        )
638
639    mandatory = schema.Bool(
640        title = _(u'Required'),
641        default = False,
642        required = False,
643        )
644
645    score = schema.Int(
646        title = _(u'Score'),
647        default = None,
648        required = False,
649        )
650
651    carry_over = schema.Bool(
652        title = _(u'Carry-over Course'),
653        default = False,
654        required = False,
655        )
656
657    automatic = schema.Bool(
658        title = _(u'Automatical Creation'),
659        default = False,
660        required = False,
661        )
662
663
664class ICourseTicketAdd(IKofaObject):
665    """An interface for adding course tickets.
666
667    """
668    course = schema.Choice(
669        title = _(u'Course'),
670        source = CourseSource(),
671        readonly = False,
672        )
673
674class ICourseTicketImport(ICourseTicket):
675    """An interface for importing course results and nothing more.
676
677    """
678    score = schema.Int(
679        title = _(u'Score'),
680        required = False,
681        readonly = False,
682        )
683
684    level_session = schema.Choice(
685        title = _(u'Level Session'),
686        source = academic_sessions_vocab,
687        required = False,
688        readonly = False,
689        )
690
691class IStudentAccommodation(IKofaObject):
692    """A container for student accommodation objects.
693
694    """
695
696    def addBedTicket(bedticket):
697        """Add a bed ticket object.
698        """
699
700
701class IBedTicket(IKofaObject):
702    """A ticket for accommodation booking.
703
704    """
705    bed = Attribute('The bed object.')
706
707    bed_coordinates = schema.TextLine(
708        title = u'',
709        required = True,
710        readonly = False,
711        )
712
713    display_coordinates = schema.TextLine(
714        title = _(u'Allocated Bed'),
715        required = False,
716        readonly = True,
717        )
718
719    bed_type = schema.TextLine(
720        title = _(u'Requested Bed Type'),
721        required = True,
722        readonly = False,
723        )
724
725    booking_session = schema.Choice(
726        title = _(u'Session'),
727        source = academic_sessions_vocab,
728        required = True,
729        readonly = True,
730        )
731
732    booking_date = schema.Datetime(
733        title = _(u'Booking Date'),
734        required = False,
735        readonly = True,
736        )
737
738    booking_code = schema.TextLine(
739        title = _(u'Booking Activation Code'),
740        required = False,
741        readonly = True,
742        )
743
744    def getSessionString():
745        """Returns the title of academic_sessions_vocab term.
746
747        """
748
749class IStudentPaymentsContainer(IPaymentsContainer):
750    """A container for student payment objects.
751
752    """
753
754class IStudentOnlinePayment(IOnlinePayment):
755    """A student payment via payment gateways.
756
757    """
758
759    p_current = schema.Bool(
760        title = _(u'Current Session Payment'),
761        default = True,
762        required = False,
763        )
764
765    p_level = schema.Int(
766        title = _(u'Payment Level'),
767        required = False,
768        )
769
770    def doAfterStudentPayment():
771        """Process student after payment was made.
772
773        """
774
775    def doAfterStudentPaymentApproval():
776        """Process student after payment was approved.
777
778        """
779
780    def approveStudentPayment():
781        """Approve payment and process student.
782
783        """
784
785IStudentOnlinePayment['p_level'].order = IStudentOnlinePayment[
786    'p_session'].order
787
788class IStudentPreviousPayment(IKofaObject):
789    """An interface for adding previous session payments.
790
791    """
792
793    p_category = schema.Choice(
794        title = _(u'Payment Category'),
795        default = u'schoolfee',
796        source = PreviousPaymentCategorySource(),
797        required = True,
798        )
799
800    p_session = schema.Choice(
801        title = _(u'Payment Session'),
802        source = academic_sessions_vocab,
803        required = True,
804        )
805
806    p_level = schema.Choice(
807        title = _(u'Payment Level'),
808        source = StudyLevelSource(),
809        required = True,
810        )
811
812class IStudentBalancePayment(IKofaObject):
813    """An interface for adding balances.
814
815    """
816
817    p_category = schema.Choice(
818        title = _(u'Payment Category'),
819        default = u'schoolfee',
820        required = True,
821        source = BalancePaymentCategorySource(),
822        )
823
824    balance_session = schema.Choice(
825        title = _(u'Payment Session'),
826        source = academic_sessions_vocab,
827        required = True,
828        )
829
830    balance_level = schema.Choice(
831        title = _(u'Payment Level'),
832        source = StudyLevelSource(),
833        required = True,
834        )
835
836    balance_amount = schema.Float(
837        title = _(u'Balance Amount'),
838        default = None,
839        required = True,
840        readonly = False,
841        description = _(
842            u'Balance in Naira '),
843        )
844
845class ICSVStudentExporter(ICSVExporter):
846    """A regular ICSVExporter that additionally supports exporting
847      data from a given student object.
848    """
849    def get_filtered(site, **kw):
850        """Get a filtered set of students.
851        """
852
853    def export_student(student, filepath=None):
854        """Export data for a given student.
855        """
856
857    def export_filtered(site, filepath=None, **kw):
858        """Export filtered set of students.
859        """
Note: See TracBrowser for help on using the repository browser.