source: WAeUP_SRP/trunk/Students.py @ 437

Last change on this file since 437 was 435, checked in by joachim, 19 years ago

removed metadata and common schemas from Student*
allow Catalog search for getFolderContents
added indizes jamb_reg_no matric_no to catalog.xml

  • Property svn:keywords set to Id
File size: 22.6 KB
RevLine 
[57]1#-*- mode: python; mode: fold -*-
[200]2# $Id: Students.py 435 2006-08-28 17:05:19Z joachim $
[45]3from Globals import InitializeClass
4from AccessControl import ClassSecurityInfo
[164]5from AccessControl.SecurityManagement import newSecurityManager
[429]6from zExceptions import BadRequest
[47]7from Products.CMFCore.utils import UniqueObject, getToolByName
[45]8from Products.CMFCore.permissions import View
9from Products.CMFCore.permissions import ModifyPortalContent
[154]10from Products.CPSCore.CPSBase import CPSBase_adder, CPSBaseFolder
11#from Products.CPSCore.CPSBase import CPSBaseDocument as BaseDocument
12from Products.CPSDocument.CPSDocument import CPSDocument
13from Products.CPSCore.CPSBase import CPSBaseBTreeFolder as BaseBTreeFolder
[164]14from Products.CPSCore.CPSMembershipTool import CPSUnrestrictedUser
[361]15from Products.WAeUP_SRP.Academics import makeCertificateCode
[362]16import logging
17import csv,re
18import Globals
19p_home = Globals.package_home(globals())
20i_home = Globals.INSTANCE_HOME
[398]21MAX_TRANS = 1000
[154]22
[422]23def generateStudentId():
24    import random
[423]25    r = random
26    return "%c%d" % (r.choice('ABCDEFGHKLMNPQRSTUVWXY'),r.randint(99999,1000000))
[422]27
[361]28class StudentsFolder(CPSDocument): ###(
29    """
30    WAeUP container for the various WAeUP containers data
31    """
[362]32    meta_type = 'StudentsFolder'
[361]33    portal_type = meta_type
34    security = ClassSecurityInfo()
[435]35    use_catalog_for_folder_contents = True
[154]36
[361]37    security.declareProtected(ModifyPortalContent,"loadFullTimeStudentsFromCSV")###(
38    def loadFullTimeStudentsFromCSV(self):
39        """load Fulltime Studentdata from CSV values"""
40        #return
[398]41        import transaction
42        tr_count = 0
[361]43        name = 'short_full_time'
44        no_import = False
[395]45        if not no_import:
46            no_import = open("%s/import/%s_not_imported.csv" % (i_home,name),"w")
47            no_import.write('"MatricNo","EntryRegNo","CurrentSession","StudentLevel","fullname","FirstName","MiddleName","Lastname","FormerSurname","Sex","Nationality","State","LGA","PermanentAddress","PermanentAddressCity","CampusAddress","PhoneNumber","Emailaddress","Mode","CourseMajor","Faculty","Dept"\n')
[361]48        logger = logging.getLogger('%s_import' % name)
49        logger.info('Start loading from %s.csv' % name)
50        students_folder = self.portal_catalog({'meta_type': 'StudentsFolder'})[-1].getObject()
51        try:
52            students = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
53        except:
54            logger.error('Error reading %s.csv' % name)
55            return
[422]56        l = self.portal_catalog({'meta_type': "StudentClearance",})
57        matrics = []
[361]58        for s in l:
[422]59            matrics.append(s.getObject().getContent().matric_no)
[423]60        print matrics
[361]61        l = self.portal_catalog({'meta_type': "Certificate"})
62        certs = {}
63        for c in l:
[362]64            certs[c.id] = c.getObject()
[361]65        for student in students:
[393]66            logger.info('processing "%(MatricNo)s","%(EntryRegNo)s","%(CurrentSession)s","%(StudentLevel)s","%(fullname)s","%(FirstName)s","%(MiddleName)s","%(Lastname)s","%(FormerSurname)s","%(Sex)s","%(Nationality)s","%(State)s","%(LGA)s","%(PermanentAddress)s","%(PermanentAddressCity)s","%(CampusAddress)s","%(PhoneNumber)s","%(Emailaddress)s","%(Mode)s","%(CourseMajor)s","%(Faculty)s","%(Dept)s"\n' % student)
[361]67            sid = student.get('MatricNo')
[396]68            if sid == "":
69                em = 'Empty MatricNo\n'
70                logger.info(em)
71                no_import.write(em)
72                no_import.write('"%(MatricNo)s","%(EntryRegNo)s","%(CurrentSession)s","%(StudentLevel)s","%(fullname)s","%(FirstName)s","%(MiddleName)s","%(Lastname)s","%(FormerSurname)s","%(Sex)s","%(Nationality)s","%(State)s","%(LGA)s","%(PermanentAddress)s","%(PermanentAddressCity)s","%(CampusAddress)s","%(PhoneNumber)s","%(Emailaddress)s","%(Mode)s","%(CourseMajor)s","%(Faculty)s","%(Dept)s"\n' % student)
73                continue
[361]74            certcode = makeCertificateCode(student.get('CourseMajor'))
75            if certcode not in certs.keys():
[393]76                em = 'Certificate with ID %s %s not found\n' % (certcode, student.get('CourseMajor'))
[361]77                logger.info(em)
[393]78                no_import.write(em)
79                no_import.write('"%(MatricNo)s","%(EntryRegNo)s","%(CurrentSession)s","%(StudentLevel)s","%(fullname)s","%(FirstName)s","%(MiddleName)s","%(Lastname)s","%(FormerSurname)s","%(Sex)s","%(Nationality)s","%(State)s","%(LGA)s","%(PermanentAddress)s","%(PermanentAddressCity)s","%(CampusAddress)s","%(PhoneNumber)s","%(Emailaddress)s","%(Mode)s","%(CourseMajor)s","%(Faculty)s","%(Dept)s"\n' % student)
[361]80                continue
[395]81            level = student.get('StudentLevel')
[426]82            try:
[395]83                int(level)
84            except:
85                em = 'Student with ID %(MatricNo)s StudentLevel is empty\n' % student
86                logger.info(em)
87                no_import.write(em)
88                no_import.write('"%(MatricNo)s","%(EntryRegNo)s","%(CurrentSession)s","%(StudentLevel)s","%(fullname)s","%(FirstName)s","%(MiddleName)s","%(Lastname)s","%(FormerSurname)s","%(Sex)s","%(Nationality)s","%(State)s","%(LGA)s","%(PermanentAddress)s","%(PermanentAddressCity)s","%(CampusAddress)s","%(PhoneNumber)s","%(Emailaddress)s","%(Mode)s","%(CourseMajor)s","%(Faculty)s","%(Dept)s"\n' % student)
89                continue
[422]90            matric_no = student.get('MatricNo')
91            if matric_no not in matrics:
92                matrics.append(matric_no)
93                sid = generateStudentId()
[361]94                #self.log('Creating Faculty %(id)s = %(Title)s' % faculty)
[426]95                logger.info('%(tr_count)s: Creating Student with ID %(sid)s Matric_no %(matric_no)s ' % vars())
[429]96                not_created = True
97                while not_created:
98                    try:
99                        students_folder.invokeFactory('Student', sid)
100                        not_created = False
101                    except BadRequest:
102                        sid = generateStudentId()
103                logger.info('%(tr_count)s: Creating Student with ID %(sid)s Matric_no %(matric_no)s ' % vars())
[361]104                s = getattr(self,sid)
105                s.invokeFactory('StudentPersonal','personal')
[362]106                sp = s.personal
[361]107                d = {'Title': 'Personal Data'}
[422]108                s.invokeFactory('StudentClearance','clearance')
[427]109                sc = s.clearance
[422]110                dc = {'Title': 'Clearance Data'}
111                dc['matric_no'] = matric_no
112                dc['jamb_reg_no'] = student.get('EntryRegNo')
[427]113                lga = student.get('State') + ' / ' + student.get('LGA')               
114                dc['lga'] = lga
[422]115                dc['nationality'] = student.get('Nationality')
116                dc['email'] = student.get('Emailaddress')
[361]117                d['firstname'] = student.get('FirstName')
118                d['middlename'] = student.get('MiddleName')
[362]119                d['lastname'] = student.get('Lastname')
[361]120                d['former_surname'] = student.get('FormerSurname')
[362]121                d['sex'] = student.get('Sex') == 'F'
[422]122                d['perm_address'] = student.get('PermanentAddress')
123                d['perm_city'] = student.get('PermanentAddressCity')
[361]124                d['campus_address'] = student.get('CampusAddress')
125                d['phone'] = student.get('PhoneNumber')
[362]126                sp.getContent().edit(mapping=d)
[422]127                sc.getContent().edit(mapping=dc)
[362]128                #
129                # Study Course
130                #
131                s.invokeFactory('StudentStudyCourse','study_course')
132                sc = s.study_course
133                d = {}
[422]134                #d['matricel_no'] = student.get('MatricNo')
135                #d['entry_reg_no'] = student.get('EntryRegNo')
136                #d['faculty'] = student.get('Faculty')
137                #d['department'] = student.get('Dept')
[362]138                d['course_major'] = certcode
139                css = student.get('CurrentSession') or '2004-2005'
140                cs = int(css.split('-')[0]) - 2000
141                cl = int(student.get('StudentLevel'))/100
142                d['entry_session'] = "200%s" % (cs - cl)
143                sc.getContent().edit(mapping=d)
[364]144                #
145                # Level
146                #
147                l = getattr(sc,level,None)
148                if l is None:
149                    #self.log('Creating Department %(DeptCode)s = %(Description)s' % dep)
150                    logger.info('Creating Level %(StudentLevel)s for %(fullname)s' % student)
151                    sc.invokeFactory('StudyLevel', level)
152                    l = getattr(sc, level)
153                    certificate = certs[certcode]
154                    cert_level = getattr(certificate,level,None)
155                    if cert_level is None:
156                        logger.info('Level %(level)s not in %(certcode)s' % vars())
157                    l.getContent().edit(mapping={'Title': "Level %s" % level})
158                    l.invokeFactory('Semester','first')
159                    l.invokeFactory('Semester','second')
160                    first_s = getattr(l,'first')
161                    first_s.getContent().edit(mapping={'Title': 'First Semester'})
162                    second_s = getattr(l,'second')
163                    second_s.getContent().edit(mapping={'Title': 'Second Semester'})
[361]164            else:
[393]165                em = 'Student with ID %(MatricNo)s %(fullname)s already exists\n' % student
[361]166                logger.info(em)
[393]167                no_import.write(em)
168                no_import.write('"%(MatricNo)s","%(EntryRegNo)s","%(CurrentSession)s","%(StudentLevel)s","%(fullname)s","%(FirstName)s","%(MiddleName)s","%(Lastname)s","%(FormerSurname)s","%(Sex)s","%(Nationality)s","%(State)s","%(LGA)s","%(PermanentAddress)s","%(PermanentAddressCity)s","%(CampusAddress)s","%(PhoneNumber)s","%(Emailaddress)s","%(Mode)s","%(CourseMajor)s","%(Faculty)s","%(Dept)s"\n' % student)
[398]169            if tr_count > MAX_TRANS:
[422]170                transaction.commit()
171                em = 'Transaction commited\n' % student
[398]172                logger.info(em)
173                tr_count = 0
174            tr_count += 1
[423]175        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
[393]176        return self.students.academics_contents()
[361]177    ###)
[382]178
[398]179    security.declareProtected(ModifyPortalContent,"loadFullTimeStudentsResultsFromCSV") ###(
[396]180    def loadFullTimeStudentsResultsFromCSV(self):
181        """load Fulltime Studentdata from CSV values"""
182        #return
[398]183        import transaction
184        tr_count = 0
185        name = 'short_full_time_results_2004_2005'
[396]186        no_import = False
187        if not no_import:
188            no_import = open("%s/import/%s_not_imported.csv" % (i_home,name),"w")
189            no_import.write('"Matnumber","CosCode","Ansbook","CosStuatus","Session","Mat_Cos","Score","CarryLevel","Grade","Weight","Semster","Verdict","Level","id","GPA"\n')
190        logger = logging.getLogger('%s_import' % name)
191        logger.info('Start loading from %s.csv' % name)
192        students_folder = self.portal_catalog({'meta_type': 'StudentsFolder'})[-1].getObject()
193        try:
194            results = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
195        except:
196            logger.error('Error reading %s.csv' % name)
197            return
198        l = self.portal_catalog({'meta_type': "Student"})
199        students = {}
200        for s in l:
201            students[s.id] = s.getObject()
[398]202        l = self.portal_catalog({'meta_type': "Course"})
203        courses = {}
204        for c in l:
205            courses[c.id] = c.getObject()
[396]206        for result in results:
207            sid = result.get('Matnumber')
[426]208            if sid not in students.keys():
[398]209                em = 'Student with ID %(Matnumber)s not found\n' % result
[396]210                logger.info(em)
211                no_import.write(em)
[398]212                no_import.write('"%(Matnumber)s","%(CosCode)s","%(Ansbook)s","%(CosStuatus)s","%(Session)s","%(Mat_Cos)s","%(Score)s","%(CarryLevel)s","%(Grade)s","%(Weight)s","%(Semster)s","%(Verdict)s","%(Level)s","%(id)s","%(GPA)s"\n' % result)
[396]213                continue
[398]214            course = result.get('CosCode')
215            if course not in courses.keys():
216                em = 'Course with ID %(CosCode)s not found\n' % result
[396]217                logger.info(em)
218                no_import.write(em)
[398]219                no_import.write('"%(Matnumber)s","%(CosCode)s","%(Ansbook)s","%(CosStuatus)s","%(Session)s","%(Mat_Cos)s","%(Score)s","%(CarryLevel)s","%(Grade)s","%(Weight)s","%(Semster)s","%(Verdict)s","%(Level)s","%(id)s","%(GPA)s"\n' % result)
[396]220                continue
[398]221            level = result.get('Level')
[426]222            try:
[396]223                int(level)
224            except:
[398]225                em = 'Result for result with ID %(Matnumber)s Course %(CosCode)s Level is empty\n' % result
[396]226                logger.info(em)
227                no_import.write(em)
[398]228                no_import.write('"%(Matnumber)s","%(CosCode)s","%(Ansbook)s","%(CosStuatus)s","%(Session)s","%(Mat_Cos)s","%(Score)s","%(CarryLevel)s","%(Grade)s","%(Weight)s","%(Semster)s","%(Verdict)s","%(Level)s","%(id)s","%(GPA)s"\n' % result)
[396]229                continue
230            sf = students.get(sid)
231            sc = getattr(sf,'study_course')
232            l = getattr(sc,level,None)
233            if l is None:
234                #self.log('Creating Department %(DeptCode)s = %(Description)s' % dep)
[398]235                logger.info('Creating Level %(Level)s for %(Matnumber)s' % result)
[396]236                sc.invokeFactory('StudyLevel', level)
237                l = getattr(sc, level)
238                l.getContent().edit(mapping={'Title': "Level %s" % level})
239                l.invokeFactory('Semester','first')
240                l.invokeFactory('Semester','second')
241                first_s = getattr(l,'first')
242                first_s.getContent().edit(mapping={'Title': 'First Semester'})
243                second_s = getattr(l,'second')
244                second_s.getContent().edit(mapping={'Title': 'Second Semester'})
[398]245            snr = result.get('Semester')
[396]246            semester = getattr(l,'first')
[398]247            if snr == "2":
[396]248                semester = getattr(l,'second')
[398]249            logger.info('Creating CourseTicket %(CourseTicket)s in Level %(Level)s for %(Matnumber)s' % result)
250            semester.invokeFactory('CourseTicket',course)
251            ct = getattr(semester,course)
252            d = {}
253            d['ansbook'] = result.get('Ansbook')
254            d['status'] = result.get('CosStuatus')
255            d['score'] = result.get('Score')
256            d['carry_level'] = result.get('CarryLevel')
257            d['grade'] = result.get('Grade')
258            d['weight'] = result.get('Weight')
259            d['verdict'] = result.get('Verdict')
260            d['import_id'] = result.get('id')
261            gpa = result.get('GPA').replace(',','.')
[426]262            d['gpa'] = float(gpa)
[398]263            ct.getContent().edit(mapping = d)
264            if tr_count > MAX_TRANS:
265                transaction.commit()
266                tr_count = 0
267            tr_count += 1
268        return self.students.academics_contents()
[426]269
[398]270###)
[396]271
[426]272
[364]273    security.declareProtected(View,"Title")
274    def Title(self):
275        """compose title"""
[382]276        return "Student Section"
[361]277
278InitializeClass(StudentsFolder)
279
280def addStudentsFolder(container, id, REQUEST=None, **kw):
281    """Add a Student."""
282    ob = StudentsFolder(id, **kw)
283    return CPSBase_adder(container, ob, REQUEST=REQUEST)
284###)
285
[57]286class Student(CPSDocument): ###(
287    """
[154]288    WAeUP Student container for the various student data
[57]289    """
290    meta_type = 'Student'
291    portal_type = meta_type
292    security = ClassSecurityInfo()
[154]293
[152]294    security.declareProtected(View,"Title")
295    def Title(self):
296        """compose title"""
[153]297        reg_nr = self.getId()[1:]
[362]298        data = getattr(self,'personal',None)
[152]299        if data is None:
[362]300            data = getattr(self,'jamb',None)
[152]301        if data:
302            content = data.getContent()
303            return "%s %s" % (content.firstname,content.lastname)
304        return self.title
[154]305
306    def Description(self):
307        """compose description"""
[170]308        data = getattr(self,'PERSONAL',None)
309        if data is None:
[191]310            return "none"
[154]311        if data:
[191]312            content = data.getContent()
313            return "%s" % (content.description)
[154]314        return self.description
315
[164]316    security.declareProtected(View,"setScratchCardData")
317    def setScratchCardData(self,ident,ds):
318        """set this data """
319        dict = {'%s_sc_pin' % ident : ds.get('sc_pin'),
320                '%s_sc_id' % ident : ds.get('sc_id'),
321                '%s_sc_value' % ident : ds.get('sc_value'),
[166]322                '%s_date' % ident : ds.get('sc_date'),
[164]323                }
[170]324
[173]325        old_user = self.portal_membership.getAuthenticatedMember()
[166]326        if self.portal_membership.isAnonymousUser():
327            tmp_user = CPSUnrestrictedUser('s%(jamb_id)s' % ds, '',
[164]328                                       ['StudentManager'], '')
[166]329            tmp_user = tmp_user.__of__(self.acl_users)
330            newSecurityManager(None, tmp_user)
331        #print str(dict)
[164]332        self.edit(mapping=dict)
[173]333        newSecurityManager(None, old_user)
[164]334
335    security.declareProtected(View,"memberIsOwner")
336    def memberIsOwner(self):
337        """is the current user the owner"""
338        member = self.portal_membership.getAuthenticatedMember()
339        #print member, self.getId(),self.aq_parent.getId()
340        if self.aq_parent.getId() == str(member):
341            return True
342        return False
343
[166]344    security.declareProtected(View,"accommodationIsBooked")
345    def accommodationIsBooked(self):
346        """is the accommodation booked"""
347        if self.accommodation_sc_pin != '':
348            return True
349        return False
350
351    security.declareProtected(View,"accommodationIsPayed")
352    def accommodationIsPayed(self):
353        """is the accommodation payed"""
[168]354        if self.hostel_fee_sc_pin != '':
[166]355            return True
356        return False
357
358    security.declareProtected(View,"isRegisteredForCurrentLevel")
359    def isRegisteredForCurrentLevel(self):
360        """is the student registered for the current level"""
361        for l in  self.aq_parent.objectValues():
362            if l.portal_type == 'StudyLevel':
363                return True
364        return False
365
[57]366InitializeClass(Student)
367
368def addStudent(container, id, REQUEST=None, **kw):
369    """Add a Student."""
370    ob = Student(id, **kw)
371    return CPSBase_adder(container, ob, REQUEST=REQUEST)
372
373###)
[91]374
[89]375class StudentPersonal(CPSDocument): ###(
376    """
[154]377    WAeUP Student container for the various student data
[89]378    """
379    meta_type = 'StudentPersonal'
380    portal_type = meta_type
381    security = ClassSecurityInfo()
[152]382
383    security.declareProtected(View,"Title")
384    def Title(self):
385        """compose title"""
386        content = self.getContent()
[364]387        #return "Personal Data for %s %s" % (content.firstname,content.lastname)
388        return "Personal Data"
[152]389
[154]390
[89]391InitializeClass(StudentPersonal)
392
393def addStudentPersonal(container, id, REQUEST=None, **kw):
394    """Add a Students personal data."""
395    ob = StudentPersonal(id, **kw)
396    return CPSBase_adder(container, ob, REQUEST=REQUEST)
397
398###)
399
[423]400class StudentClearance(CPSDocument): ###(
401    """
402    WAeUP Student container for the various student data
403    """
404    meta_type = 'StudentClearance'
405    portal_type = meta_type
406    security = ClassSecurityInfo()
407
408    security.declareProtected(View,"Title")
409    def Title(self):
410        """compose title"""
411        content = self.getContent()
412        #return "Clearance Data for %s %s" % (content.firstname,content.lastname)
413        return "Clearance Data"
414
415
416InitializeClass(StudentClearance)
417
418def addStudentClearance(container, id, REQUEST=None, **kw):
419    """Add a Students personal data."""
420    ob = StudentClearance(id, **kw)
421    return CPSBase_adder(container, ob, REQUEST=REQUEST)
422
423###)
424
[362]425class StudentStudyCourse(CPSDocument): ###(
426    """
427    WAeUP Student container for the various student data
428    """
429    meta_type = 'StudentStudyCourse'
430    portal_type = meta_type
431    security = ClassSecurityInfo()
432
[364]433    security.declareProtected(View,"Title")
434    def Title(self):
435        """compose title"""
436        content = self.getContent()
[382]437        return "Course Major"
[362]438
439
440InitializeClass(StudentStudyCourse)
441
442def addStudentStudyCourse(container, id, REQUEST=None, **kw):
443    """Add a Students personal data."""
444    ob = StudentStudyCourse(id, **kw)
445    return CPSBase_adder(container, ob, REQUEST=REQUEST)
446
447###)
448
[423]449class StudentAdmission(CPSDocument): ###(
[179]450    """
451    WAeUP Student container for the various student data
452    """
[423]453    meta_type = 'StudentAdmission'
[179]454    portal_type = meta_type
455    security = ClassSecurityInfo()
456
[181]457    security.declareProtected(View,"Title")
458    def Title(self):
459        """compose title"""
[423]460        return "Admission Data"
[179]461
[181]462
[423]463InitializeClass(StudentAdmission)
[179]464
[423]465def addStudentAdmission(container, id, REQUEST=None, **kw):
[179]466    """Add a Students eligibility data."""
[423]467    ob = StudentAdmission(id, **kw)
[179]468    return CPSBase_adder(container, ob, REQUEST=REQUEST)
469
470###)
[181]471
[166]472class StudentDocuments(CPSDocument): ###(
473    """
474    WAeUP Student container for the various student data
475    """
476    meta_type = 'StudentDocuments'
477    portal_type = meta_type
478    security = ClassSecurityInfo()
479
480    security.declareProtected(View,"Title")
481    def Title(self):
482        """compose title"""
483        content = self.getContent()
484        return "Scanned Documents"
485
486
487InitializeClass(StudentDocuments)
488
489def addStudentDocuments(container, id, REQUEST=None, **kw):
490    """Add a Students documents"""
491    ob = StudentDocuments(id, **kw)
492    return CPSBase_adder(container, ob, REQUEST=REQUEST)
493
494###)
495
[89]496class Jamb(CPSDocument): ###(
497    """
498    WAeUP Jamb containing the courses and students
499    """
500    meta_type = 'Jamb'
501    portal_type = meta_type
502    security = ClassSecurityInfo()
[154]503
[152]504    security.declareProtected(View,"Title")
505    def Title(self):
506        """compose title"""
507        content = self.getContent()
508        return "JAMB Data for %s %s" % (content.firstname,content.lastname)
509
510    security.declareProtected(View,"setOwnership")
511    def setOwnership(self,member_id):
512        """set ownership"""
513        pm = getattr(self,'portal_membership')
514        member = pm.getMemberById(member_id)
515        self.changeOwnership(member)
516
[89]517InitializeClass(Jamb)
518
519def addJamb(container, id, REQUEST=None, **kw):
520    """Add a Jamb."""
521    ob = Jamb(id, **kw)
522    return CPSBase_adder(container, ob, REQUEST=REQUEST)
523
[139]524###)
525
526class StudyLevel(CPSDocument): ###(
527    """
528    WAeUP StudyLevel containing the courses and students
529    """
530    meta_type = 'StudyLevel'
531    portal_type = meta_type
532    security = ClassSecurityInfo()
[154]533
[139]534InitializeClass(StudyLevel)
535
536def addStudyLevel(container, id, REQUEST=None, **kw):
537    """Add a StudyLevel."""
538    ob = StudyLevel(id, **kw)
539    return CPSBase_adder(container, ob, REQUEST=REQUEST)
540
541###)
542
543class Semester(CPSDocument): ###(
544    """
545    WAeUP Semester containing the courses and students
546    """
547    meta_type = 'Semester'
548    portal_type = meta_type
549    security = ClassSecurityInfo()
[154]550
[139]551InitializeClass(Semester)
552
553def addSemester(container, id, REQUEST=None, **kw):
554    """Add a Semester."""
555    ob = Semester(id, **kw)
556    return CPSBase_adder(container, ob, REQUEST=REQUEST)
[200]557
[139]558###)
559
Note: See TracBrowser for help on using the repository browser.