source: WAeUP_SRP/trunk/Students.py @ 959

Last change on this file since 959 was 959, checked in by joachim, 18 years ago

slight improvements of pume import

  • Property svn:keywords set to Id
File size: 48.0 KB
Line 
1#-*- mode: python; mode: fold -*-
2# $Id: Students.py 959 2006-11-28 13:18:53Z joachim $
3from string import Template
4from Globals import InitializeClass
5from AccessControl import ClassSecurityInfo
6from AccessControl.SecurityManagement import newSecurityManager
7from zExceptions import BadRequest
8from Products.ZCatalog.ZCatalog import ZCatalog
9from Products.CMFCore.utils import UniqueObject, getToolByName
10from Products.CMFCore.permissions import View
11from Products.CMFCore.permissions import ModifyPortalContent
12from Products.CPSCore.CPSBase import CPSBase_adder, CPSBaseFolder
13#from Products.CPSCore.CPSBase import CPSBaseDocument as BaseDocument
14from Products.CPSDocument.CPSDocument import CPSDocument
15from Products.CPSCore.CPSBase import CPSBaseBTreeFolder as BaseBTreeFolder
16from Products.CPSCore.CPSMembershipTool import CPSUnrestrictedUser
17from Products.WAeUP_SRP.Academics import makeCertificateCode
18import logging
19import csv,re
20import Globals
21p_home = Globals.package_home(globals())
22i_home = Globals.INSTANCE_HOME
23MAX_TRANS = 100
24
25def makeCertificateCode(code): ###(
26    code = code.replace('.','')
27    code = code.replace('(','')
28    code = code.replace(')','')
29    code = code.replace('/','')
30    code = code.replace(' ','')
31    code = code.replace('_','')
32    return code
33
34###)
35
36def getInt(s): ###(
37    try:
38        return int(s)
39    except:
40        return 0
41
42def getFloat(s):
43    try:
44        return float(s)
45    except:
46        return 0.0
47
48###)
49
50def getStudentByRegNo(self,reg_no): ###(
51    """search student by JAMB Reg No and return StudentFolder"""
52    search = ZCatalog.searchResults(self.portal_catalog,{'meta_type': 'StudentApplication',
53                                  'SearchableText': reg_no,
54                                  })
55    if len(search) < 1:
56        return None
57    return search[0].getObject().aq_parent
58
59###)
60
61class StudentsFolder(CPSDocument): ###(
62    """
63    WAeUP container for the various WAeUP containers data
64    """
65    meta_type = 'StudentsFolder'
66    portal_type = meta_type
67    security = ClassSecurityInfo()
68
69    security.declareProtected(ModifyPortalContent,"loadFullTimeStudentsFromCSV")###(
70    def loadFullTimeStudentsFromCSV(self):
71        """load Fulltime Studentdata from CSV values"""
72        import transaction
73        import random
74        tr_count = 0
75        name = 'short_full_time'
76        no_import = False
77        if not no_import:
78            no_import = open("%s/import/%s_not_imported.csv" % (i_home,name),"w")
79            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')
80        logger = logging.getLogger('%s_import' % name)
81        logger.info('Start loading from %s.csv' % name)
82        pwlist  = []
83        pwlist.append('"student_id","firstname","middlename","lastname","matric_no","jamb_reg_no","access_code"')
84        pwl_template = Template('"$student_id","$firstname","$middlename","$lastname","$matric_no","$jamb_reg_no","$access_code"')
85        students_folder = self.portal_catalog({'meta_type': 'StudentsFolder'})[-1].getObject()
86        try:
87            students = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
88        except:
89            logger.error('Error reading %s.csv' % name)
90            return
91        l = self.portal_catalog({'meta_type': "StudentClearance",})
92        matrics = []
93        for s in l:
94            matrics.append(s.getObject().getContent().matric_no)
95        print matrics
96        l = self.portal_catalog({'meta_type': "Certificate"})
97        certs = {}
98        for c in l:
99            ca,ac,fa,dep_id,co,certcode = c.relative_path.split('/')
100            cid = "%(dep_id)s_%(certcode)s" % vars()
101            certs[cid] = c.getObject()
102        for student in students:
103            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)
104            sid = student.get('MatricNo')
105            if sid == "":
106                em = 'Empty MatricNo\n'
107                logger.info(em)
108                no_import.write(em)
109                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)
110                continue
111            certcode = makeCertificateCode(student.get('CourseMajor'))
112            dep_id = student.get('Dept')
113            fac_id = student.get('Faculty')
114            cid = "%(dep_id)s_%(certcode)s" % vars()
115            if cid not in certs.keys():
116                em = 'Certificate with ID %s %s not found\n' % (certcode, student.get('CourseMajor'))
117                logger.info(em)
118                no_import.write(em)
119                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)
120                continue
121            certificate_doc = certs[cid].getContent()
122            level = student.get('StudentLevel')
123            try:
124                int(level)
125            except:
126                em = 'Student with ID %(MatricNo)s StudentLevel is empty\n' % student
127                logger.info(em)
128                no_import.write(em)
129                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)
130                continue
131            matric_no = student.get('MatricNo')
132            if matric_no not in matrics:
133                matrics.append(matric_no)
134                sid = self.generateStudentId(student.get('Lastname')[0])
135                #self.log('Creating Faculty %(id)s = %(Title)s' % faculty)
136                students_folder.invokeFactory('Student', sid)
137                logger.info('%(tr_count)s: Creating Student with ID %(sid)s Matric_no %(matric_no)s ' % vars())
138                student_obj = getattr(self,sid)
139                access_code = "%d" % random.randint(1000000000,9999999999)
140                student_obj.getContent().makeStudentMember(sid,access_code,)
141                pwl_dict = {'student_id': sid,'access_code':access_code}
142                student_obj.invokeFactory('StudentApplication','application')
143                application = student_obj.application
144                da = {'Title': 'Application Data'}
145                student_obj.invokeFactory('StudentPersonal','personal')
146                da['jamb_reg_no'] = student.get('EntryRegNo')
147                personal = student_obj.personal
148                dp = {'Title': 'Personal Data'}
149                student_obj.invokeFactory('StudentClearance','clearance')
150                clearance = student_obj.clearance
151                dc = {'Title': 'Clearance/Eligibility Record'}
152                dc['matric_no'] = matric_no
153                state = student.get('State')
154                lga = student.get('LGA')
155                if state and lga:
156                    lga =  state + ' / ' + lga
157                else:
158                    lga = "None"
159                dc['lga'] = lga
160                dc['nationality'] = student.get('Nationality')
161                dc['email'] = student.get('Emailaddress')
162                dp['firstname'] = student.get('FirstName')
163                dp['middlename'] = student.get('MiddleName')
164                dp['lastname'] = student.get('Lastname')
165                dp['former_surname'] = student.get('FormerSurname')
166                dp['sex'] = student.get('Sex') == 'F'
167                dp['perm_address'] = student.get('PermanentAddress')
168                dp['perm_city'] = student.get('PermanentAddressCity')
169                dp['campus_address'] = student.get('CampusAddress')
170                dp['phone'] = student.get('PhoneNumber')
171                application.getContent().edit(mapping=da)
172                personal.getContent().edit(mapping=dp)
173                clearance.getContent().edit(mapping=dc)
174                #
175                # Study Course
176                #
177                student_obj.invokeFactory('StudentStudyCourse','study_course')
178                studycourse = student_obj.study_course
179                dsc = {}
180                from_certificate = ['title',
181                                   'max_elect',
182                                   'max_pass',
183                                   'n_core',
184                                   'nr_years',
185                                   'probation_credits',
186                                   'promotion_credits',
187                                   'start_level',
188                                  ]
189                for f in from_certificate:
190                    dsc[f] = getattr(certificate_doc,f)
191                dsc['faculty'] = fac_id
192                dsc['department'] = dep_id
193                dsc['study_course'] = certcode
194                css = student.get('CurrentSession') or '2004-2005'
195                cs = int(css.split('-')[0]) - 2000
196                cl = int(student.get('StudentLevel') or '100')/100
197                dsc['entry_session'] = "200%s" % (cs - cl)
198                dsc['clr_ac_pin'] = access_code
199                studycourse.getContent().edit(mapping=dsc)
200                #
201                # Level
202                #
203##                l = getattr(studycourse,level,None)
204##                if 0 and l is None:
205##                    #self.log('Creating Department %(DeptCode)s = %(Description)s' % dep)
206##                    logger.info('Creating Level %(StudentLevel)s for %(fullname)s' % student)
207##                    studycourse.invokeFactory('StudentStudyLevel', level)
208##                    l = getattr(studycourse, level)
209##                    certificate = certs[certcode]
210##                    cert_level = getattr(certificate,level,None)
211##                    if cert_level is None:
212##                        logger.info('Level %(level)s not in %(certcode)s' % vars())
213##                    l.getContent().edit(mapping={'Title': "Level %s" % level})
214            else:
215                em = 'Student with ID %(MatricNo)s %(fullname)s already exists\n' % student
216                logger.info(em)
217                no_import.write(em)
218                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)
219                continue
220            if tr_count > MAX_TRANS:
221                transaction.commit()
222                em = 'Transaction commited\n' % student
223                logger.info(em)
224                tr_count = 0
225            tr_count += 1
226            pwl_dict.update(dc)
227            pwl_dict.update(da)
228            pwl_dict.update(dp)
229            wftool = self.portal_workflow
230            pwlist.append(pwl_template.substitute(pwl_dict))
231            wftool.doActionFor(student_obj,'clear_and_validate')
232            student_obj.manage_setLocalRoles(sid, ['Owner',])
233            wftool.doActionFor(application,'close')
234            application.manage_setLocalRoles(sid, ['Owner',])
235            wftool.doActionFor(clearance,'close')
236            clearance.manage_setLocalRoles(sid, ['Owner',])
237            wftool.doActionFor(personal,'close')
238            personal.manage_setLocalRoles(sid, ['Owner',])
239            wftool.doActionFor(studycourse,'close_for_edit')
240            studycourse.manage_setLocalRoles(sid, ['Owner',])
241        open("%s/import/pwlist-%s.csv" % (i_home,name),"w+").write('\n'.join(pwlist))
242        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
243    ###)
244
245    security.declareProtected(ModifyPortalContent,"loadPumeResultsFromCSV")###(
246    def loadPumeResultsFromCSV(self):
247        """load Fulltime Studentdata from CSV values"""
248        import transaction
249        import random
250        from pdb import set_trace
251        wftool = self.portal_workflow
252        students_folder = self.portal_catalog({'meta_type': 'StudentsFolder'})[-1].getObject()
253        csv_d = {'jamb_reg_no': "JAMBRegno",
254                 'jamb_lastname': "Name",
255                 #'pume_options': "Options",
256                 #'session': "Session",
257                 #'days': "Days",
258                 #'response': "Responce",
259                 #'wrong': "Wrong",
260                 #'pume_eng_score': "EngScore",
261                 #'pume_gen_score': "GenScore",
262                 'pume_tot_score': "Score",
263                 #'batch': "Batch",
264                 #'serial': "SerialNo",
265                 #'jamb_score': "JambScore",
266                 #'omitted':"Omitted",
267                 #'search_key': "SearchKey",
268                 'jamb_sex': "Sex",
269                 'fac1': "Faculty",
270                 'dep': "Dept",
271                 #'fac2': "Fac2",
272                 'jamb_first_cos': "Course Code",
273                 'stud_status':"Admission Status",
274                 #'registered': "Registered",
275                 #'jamb_state': "State",
276                 #'eng_fail': "EngFail",
277                 #'gen_fail': "GenFail",
278                 #'un_ans_eng': "UnAnsEng",
279                 #'un_ans_eng': "UnAnsGen",
280                 #'total_ans': "TotalUnAns",
281                 #'dept': "Dept",
282                 #'jamb_second_cos': "Course2",
283                 #'jamb_third_cos': "course3",
284                 }
285        csv_fields = [f[1] for f in csv_d.items()]
286        tr_count = 0
287        #name = 'pume_results'
288        name = 'pup'
289        no_import = []
290        s = ','.join(['"(%s)"' % fn for fn in csv_fields])
291        no_import.append('%s\n' % s)
292        logger = logging.getLogger('%s_import' % name)
293        logger.info('Start loading from %s.csv' % name)
294        #set_trace()
295        try:
296            result = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
297        except:
298            logger.error('Error reading %s.csv' % name)
299            return
300        for jamb in result:
301            format = ','.join(['"%%(%s)s"' % fn for fn in csv_fields])
302            processing = "processing %s" % format
303            logger.info(processing % jamb)
304            jamb_reg_no = jamb.get(csv_d['jamb_reg_no'])
305            #import pdb;pdb.set_trace()
306            res = self.portal_catalog({'portal_type': "StudentApplication",
307                                     'SearchableText': jamb_reg_no })
308            if res:
309                em = 'Student with REG-NO %s already exists\n' % jamb_reg_no
310                logger.info(em)
311                no_import.append(em)
312                no_import.append(format % jamb)
313                continue
314            cert_id = makeCertificateCode(jamb.get(csv_d['jamb_first_cos']))
315            res = self.portal_catalog({'portal_type': "Certificate",
316                                     'id': cert_id })
317            if len(res) < 1:
318                em = 'No Certificate with ID %s \n' % cert_id
319                logger.info(em)
320                no_import.append(em)
321                no_import.append(format % jamb)
322                continue
323            cert = res[0].getObject()
324            cert_path = res[0].getPath()
325            cert_doc = cert.getContent()
326            jamb_name = jamb.get(csv_d['jamb_lastname'])
327            jamb_name.replace('>','')
328            names = jamb_name.split()
329            letter = names[-1][0].upper()
330            sid = self.generateStudentId(letter)
331            not_created = True
332            while not_created:
333                try:
334                    students_folder.invokeFactory('Student', sid)
335                    not_created = False
336                except BadRequest:
337                    sid = self.generateStudentId(letter)
338            tr_count += 1
339            logger.info('%(tr_count)s: Creating Student with ID %(sid)s REG-NO %(jamb_reg_no)s ' % vars())
340            student = getattr(self,sid)
341            student.manage_setLocalRoles(sid, ['Owner',])
342            student.invokeFactory('StudentClearance','clearance')
343            #wftool.doActionFor(student.clearance,'open')
344            dp = {'Title': 'Clearance/Eligibility Record'}
345            student.clearance.manage_setLocalRoles(sid, ['Owner',])
346            student.invokeFactory('StudentPume','pume')
347            dp = {'Title': 'Pume Data'}
348            student.invokeFactory('StudentApplication','application')
349            da = {'Title': 'Application Data'}
350            da["jamb_lastname"] = jamb_name
351            da_fields = ('jamb_reg_no',
352                         'jamb_sex',
353                         #'jamb_state',
354                         #'jamb_score',
355                         'jamb_first_cos',
356                         'jamb_sex',
357                         #'jamb_state',
358                         #'jamb_first_cos',
359                         #'jamb_second_cos',
360                         )
361            for f in da_fields:
362                da[f] = jamb.get(csv_d[f])
363            app = student.application
364            app.getContent().edit(mapping=da)
365            app.manage_setLocalRoles(sid, ['Owner',])
366            #wftool.doActionFor(app,'close')
367            dp_fields = (
368                         #'pume_eng_score',
369                         #'pume_gen_score',
370                         'pume_tot_score',
371                         )
372            for f in dp_fields:
373                try:
374                    dp[f] = float(jamb.get(csv_d[f]))
375                except ValueError:
376                    dp[f] = 0.0
377            pume = student.pume
378            pume.getContent().edit(mapping=dp)
379            #wftool.doActionFor(pume,'close')
380            pume.manage_setLocalRoles(sid, ['Owner',])
381            #
382            # Study Course
383            #
384            if jamb.get(csv_d['stud_status']) == "Admitted":
385                wftool.doActionFor(student,'pume_pass')
386                wftool.doActionFor(student,'admit')
387            else:
388                wftool.doActionFor(student,'pume_fail')
389                wftool.doActionFor(student,'reject_admission')
390                continue
391            student.invokeFactory('StudentStudyCourse','study_course')
392            study_course = student.study_course
393            dsc = {}
394            from_certificate = ['title',
395                               'max_elect',
396                               'max_pass',
397                               'n_core',
398                               'nr_years',
399                               'probation_credits',
400                               'promotion_credits',
401                               'start_level',
402                              ]
403            for f in from_certificate:
404                dsc[f] = getattr(cert_doc,f)
405            cpl = cert_path.split('/')
406            dsc['faculty'] = cpl[-4]
407            dsc['department'] = cpl[-3]
408            dsc['study_course'] = cert_id
409            dsc['entry_session'] = "2006/2007" #jamb.get(csv_d['session'])
410            study_course.getContent().edit(mapping=dsc)
411            student.getContent().createSubObjects()
412            if tr_count > MAX_TRANS:
413                transaction.commit()
414                em = '%d transactions commited\n' % tr_count
415                logger.info(em)
416                tr_count = 0
417        if len(no_import) > 1:
418            open("%s/import/%s_not_imported.csv" % (i_home,name),"w").write(
419                     '\n'.join(no_import))
420        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
421    ###)
422
423    security.declareProtected(ModifyPortalContent,"OLDloadPumeResultsFromCSV")###(
424    def OLDloadPumeResultsFromCSV(self):
425        """load Fulltime Studentdata from CSV values"""
426        import transaction
427        import random
428        wftool = self.portal_workflow
429        students_folder = self.portal_catalog({'meta_type': 'StudentsFolder'})[-1].getObject()
430        csv_d = {'jamb_reg_no': "JAMBRegno",
431                 'jamb_lastname': "Name",
432                 'pume_options': "Options",
433                 'session': "Session",
434                 'days': "Days",
435                 'response': "Responce",
436                 'wrong': "Wrong",
437                 'pume_eng_score': "EngScore",
438                 'pume_gen_score': "GenScore",
439                 'pume_tot_score': "Score",
440                 'batch': "Batch",
441                 'serial': "SerialNo",
442                 'jamb_score': "JambScore",
443                 'omitted':"Omitted",
444                 'search_key': "SearchKey",
445                 'jamb_sex': "Sex",
446                 'fac1': "Fac1",
447                 'fac2': "Fac2",
448                 'jamb_first_cos': "CourseofStudy",
449                 'stud_status':"StudStatus",
450                 'registered': "Registered",
451                 'jamb_state': "State",
452                 'eng_fail': "EngFail",
453                 'gen_fail': "GenFail",
454                 'un_ans_eng': "UnAnsEng",
455                 'un_ans_eng': "UnAnsGen",
456                 'total_ans': "TotalUnAns",
457                 'dept': "Dept",
458                 'jamb_second_cos': "Course2",
459                 'jamb_third_cos': "course3",
460                 }
461        csv_fields = [f[1] for f in csv_d.items()]
462        tr_count = 0
463        name = 'pume_results'
464        no_import = []
465        s = ','.join(['"(%s)"' % fn for fn in csv_fields])
466        no_import.append('%s\n' % s)
467        logger = logging.getLogger('%s_import' % name)
468        logger.info('Start loading from %s.csv' % name)
469        try:
470            result = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
471        except:
472            logger.error('Error reading %s.csv' % name)
473            return
474        for jamb in result:
475            format = ','.join(['"%%(%s)s"' % fn for fn in csv_fields])
476            processing = "processing %s" % format
477            logger.info(processing % jamb)
478            jamb_reg_no = jamb.get(csv_d['jamb_reg_no'])
479            #import pdb;pdb.set_trace()
480            res = self.portal_catalog({'portal_type': "StudentApplication",
481                                     'jamb_reg_no': jamb_reg_no })
482            if res:
483                em = 'Student with REG-NO %s already exists\n' % jamb_reg_no
484                logger.info(em)
485                no_import.append(em)
486                no_import.append(format % jamb)
487                continue
488            cert_id = jamb.get(csv_d['jamb_first_cos']).upper()
489            res = self.portal_catalog({'portal_type': "Certificate",
490                                     'id': cert_id })
491            if len(res) < 1:
492                em = 'No Certificate with ID %s \n' % cert_id
493                logger.info(em)
494                no_import.append(em)
495                no_import.append(format % jamb)
496                continue
497            cert = res[0].getObject()
498            cert_path = res[0].getPath()
499            cert_doc = cert.getContent()
500            jamb_name = jamb.get(csv_d['jamb_lastname'])
501            jamb_name.replace('>','')
502            names = jamb_name.split()
503            letter = names[-1][0].upper()
504            sid = self.generateStudentId(letter)
505            not_created = True
506            while not_created:
507                try:
508                    students_folder.invokeFactory('Student', sid)
509                    not_created = False
510                except BadRequest:
511                    sid = self.generateStudentId(letter)
512            logger.info('%(tr_count)s: Creating Student with ID %(sid)s REG-NO %(jamb_reg_no)s ' % vars())
513            student = getattr(self,sid)
514            student.manage_setLocalRoles(sid, ['Owner',])
515            student.invokeFactory('StudentClearance','clearance')
516            #wftool.doActionFor(student.clearance,'open')
517            dp = {'Title': 'Clearance/Eligibility Record'}
518            student.clearance.manage_setLocalRoles(sid, ['Owner',])
519            student.invokeFactory('StudentPume','pume')
520            dp = {'Title': 'Pume Data'}
521            student.invokeFactory('StudentApplication','application')
522            da = {'Title': 'Application Data'}
523            da["jamb_lastname"] = jamb_name
524            da_fields = ('jamb_reg_no',
525                         'jamb_sex',
526                         'jamb_state',
527                         'jamb_score',
528                         'jamb_first_cos',
529                         'jamb_sex',
530                         'jamb_state',
531                         'jamb_first_cos',
532                         'jamb_second_cos',
533                         )
534            for f in da_fields:
535                da[f] = jamb.get(csv_d[f])
536            app = student.application
537            app.getContent().edit(mapping=da)
538            app.manage_setLocalRoles(sid, ['Owner',])
539            #wftool.doActionFor(app,'close')
540            dp_fields = (
541                         'pume_eng_score',
542                         'pume_gen_score',
543                         'pume_tot_score',
544                         )
545            for f in dp_fields:
546                dp[f] = float(jamb.get(csv_d[f]))
547            pume = student.pume
548            pume.getContent().edit(mapping=dp)
549            #wftool.doActionFor(pume,'close')
550            pume.manage_setLocalRoles(sid, ['Owner',])
551            #
552            # Study Course
553            #
554            student.invokeFactory('StudentStudyCourse','study_course')
555            study_course = student.study_course
556            dsc = {}
557            from_certificate = ['title',
558                               'max_elect',
559                               'max_pass',
560                               'n_core',
561                               'nr_years',
562                               'probation_credits',
563                               'promotion_credits',
564                               'start_level',
565                              ]
566            for f in from_certificate:
567                dsc[f] = getattr(cert_doc,f)
568            cpl = cert_path.split('/')
569            dsc['faculty'] = cpl[-4]
570            dsc['department'] = cpl[-3]
571            dsc['study_course'] = cert_id
572            dsc['entry_session'] = jamb.get(csv_d['session'])
573            study_course.getContent().edit(mapping=dsc)
574            student.getContent().createSubObjects()
575            if dp['pume_tot_score']>49:
576                wftool.doActionFor(student,'pume_pass')
577                wftool.doActionFor(student,'admit')
578            else:
579                wftool.doActionFor(student,'pume_fail')
580                wftool.doActionFor(student,'reject_admission')
581            if len(no_import) > 1:
582                open("%s/import/%s_not_imported.csv" % (i_home,name),"w").write(
583                     '\n'.join(no_import))
584        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
585    ###)
586
587    security.declareProtected(ModifyPortalContent,"loadFullTimeStudentsResultsFromCSV") ###(
588    def loadFullTimeStudentsResultsFromCSV(self):
589        """load Fulltime Studentdata from CSV values"""
590        #return
591        level_wf_actions = {}
592        level_wf_actions["SUCCESSFUL STUDENT"] = "pass_A"
593        level_wf_actions["STUDENT WITH CARRYOVER COURSES"] = "pass_B"
594        level_wf_actions["STUDENT FOR PROBATION"] = "probate_C"
595        level_wf_actions["STUDENT ON PROBATION/TRANSFER"] = "reject_D"
596        import transaction
597        wftool = self.portal_workflow
598        tr_count = 0
599        name = 'short_full_time_results_2004_2005'
600        no_import = False
601        if not no_import:
602            no_import = open("%s/import/%s_not_imported.csv" % (i_home,name),"w")
603            no_import.write('"Matnumber","CosCode","Ansbook","CosStuatus","Session","Mat_Cos","Score","CarryLevel","Grade","Weight","Semster","Verdict","Level","id","GPA"\n')
604        logger = logging.getLogger('%s_import' % name)
605        logger.info('Start loading from %s.csv' % name)
606        students_folder = self.portal_catalog({'meta_type': 'StudentsFolder'})[-1].getObject()
607        try:
608            results = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
609        except:
610            logger.error('Error reading %s.csv' % name)
611            return
612        l = self.portal_catalog({'meta_type': "Course"})
613        courses = {}
614        for c in l:
615            courses[c.id] = c.getObject()
616        level_changed = False
617        student_changed = False
618        sid = ''
619        #import pdb;pdb.set_trace()
620        for result in results:
621            temp_sid = result.get('Matnumber')
622            if temp_sid != sid:
623                student_changed = True
624                res = self.portal_catalog({'meta_type': "StudentClearance",
625                                         'SearchableText': temp_sid })
626                if not res:
627                    em = 'Student with ID %(Matnumber)s not found\n' % result
628                    logger.info(em)
629                    no_import.write(em)
630                    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)
631                    continue
632                elif len(res) > 1:
633                    em = 'More than one Student with ID %(Matnumber)s found\n' % result
634                    logger.info(em)
635                    no_import.write(em)
636                    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)
637                    continue
638                sid = temp_sid
639                sf = res[0].getObject().aq_parent
640                sc = getattr(sf,'study_course')
641                level = ''
642            else:
643                student_changed = False
644            course = result.get('CosCode')
645            if course not in courses.keys():
646                em = 'Course with ID %(CosCode)s not found\n' % result
647                logger.info(em)
648                no_import.write(em)
649                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)
650                continue
651            course_doc = courses[course].getContent()
652            temp_level = result.get('Level')
653            student_id = sf.getId()
654            result['StudentId'] = student_id
655            if temp_level != level:
656                try:
657                    int(temp_level)
658                except:
659                    em = 'Result with ID %(Matnumber)s Course %(CosCode)s Level is empty\n' % result
660                    logger.info(em)
661                    no_import.write(em)
662                    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)
663                    continue
664                level_changed = True
665                if 'dlev' in vars().keys():
666                    wftool.doActionFor(l,level_wf_actions[dlev['verdict']])
667                level = temp_level
668                l = getattr(sc,level,None)
669                if l is None:
670                    logger.info('Creating Level %(Level)s for %(StudentId)s %(Matnumber)s' % result)
671                    sc.invokeFactory('StudentStudyLevel', level)
672                    l = getattr(sc, level)
673                    l.manage_setLocalRoles(student_id, ['Owner',])
674            else:
675                level_changed = False
676            cr = getattr(l,course,None)
677            if cr is None:
678                logger.info('Creating Course %(CosCode)s for %(StudentId)s %(Matnumber)s in Level %(Level)s' % result)
679                l.invokeFactory('StudentCourseResult',course)
680            cr = getattr(l,course)
681            dcr = {}
682            from_course = ['title',
683                           'credits',
684                           'passmark',
685                           ]
686            for f in from_course:
687                dcr[f] = getattr(course_doc,f)
688            dlev = {}
689            dcr['ansbook'] = result.get('Ansbook')
690            dcr['semester'] = getInt(result.get('Semster'))
691            dcr['status'] = result.get('CosStuatus')
692            dcr['score'] = getInt(result.get('Score'))
693            dlev['session'] = result.get('Session')
694            dcr['carry_level'] = result.get('CarryLevel')
695            dcr['grade'] = result.get('Grade')
696            dcr['weight'] = result.get('Weight')
697            dlev['verdict'] = result.get('Verdict')
698            dcr['import_id'] = result.get('id')
699            gpa = result.get('GPA').replace(',','.')
700            dlev['imported_gpa'] = getFloat(gpa)
701            cr.getContent().edit(mapping = dcr)
702            cr.manage_setLocalRoles(student_id, ['Owner',])
703            l.getContent().edit(mapping = dlev)
704            if tr_count > MAX_TRANS:
705                transaction.commit()
706                tr_count = 0
707            tr_count += 1
708            wftool.doActionFor(cr,'close')
709        wftool.doActionFor(l,level_wf_actions[dlev['verdict']])
710        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
711
712###)
713
714    security.declareProtected(ModifyPortalContent,"loadJAMBFromCSV")###(
715    def loadJAMBFromCSV(self):
716        """load JAMB data from CSV values"""
717        #return
718        students_folder = self.portal_catalog({'meta_type': 'StudentsFolder'})[-1].getObject()
719        import transaction
720        tr_count = 0
721        name = 'SampleJAMBDataII'
722        wftool = self.portal_workflow
723        no_import = False
724        if not no_import:
725            no_import = open("%s/import/%s_not_imported.csv" % (i_home,name),"w")
726            no_import.write('REG-NO,NAME,SEX,STATE,LGA,ENG-SCORE,SUBJ1,SUBJ1-SCORE,SUBJ2,SUBJ2-SCORE,SUBJ3,SUBJ3-SCORE,AGGREGATE,UNIV1,FACULTY1,COURSE1,UNIV2,FACULTY2,COURSE2')
727        logger = logging.getLogger('%s_import' % name)
728        logger.info('Start loading from %s.csv' % name)
729        try:
730            result = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
731        except:
732            logger.error('Error reading %s.csv' % name)
733            return
734        for jamb in result:
735            logger.info('processing %(REG-NO)s,%(NAME)s,%(SEX)s,%(STATE)s,%(LGA)s,%(ENG-SCORE)s,%(SUBJ1)s,%(SUBJ1-SCORE)s,%(SUBJ2)s,%(SUBJ2-SCORE)s,%(SUBJ3)s,%(SUBJ3-SCORE)s,%(AGGREGATE)s,%(UNIV1)s,%(FACULTY1)s,%(COURSE1)s,%(UNIV2)s,%(FACULTY2)s,%(COURSE2)s\n' % jamb)
736            jamb_reg_no = jamb.get('REG-NO')
737            res = self.portal_catalog({'meta_type': "StudentApplication",
738                                     'jamb_reg_no': jamb_reg_no })
739            if res:
740                em = 'Student with REG-NO %(REG-NO)s already exists\n' % jamb
741                logger.info(em)
742                no_import.write(em)
743                no_import.write('%(REG-NO)s,%(NAME)s,%(SEX)s,%(STATE)s,%(LGA)s,%(ENG-SCORE)s,%(SUBJ1)s,%(SUBJ1-SCORE)s,%(SUBJ2)s,%(SUBJ2-SCORE)s,%(SUBJ3)s,%(SUBJ3-SCORE)s,%(AGGREGATE)s,%(UNIV1)s,%(FACULTY1)s,%(COURSE1)s,%(UNIV2)s,%(FACULTY2)s,%(COURSE2)s\n' % jamb)
744                continue
745            jamb_name = jamb.get("NAME")
746            jamb_name.replace('>','')
747            names = jamb_name.split()
748            letter = names[-1][0].upper()
749            sid = self.generateStudentId(letter)
750            not_created = True
751            while not_created:
752                try:
753                    students_folder.invokeFactory('Student', sid)
754                    not_created = False
755                except BadRequest:
756                    sid = self.generateStudentId(letter)
757            logger.info('%(tr_count)s: Creating Student with ID %(sid)s REG-NO %(jamb_reg_no)s ' % vars())
758            student = getattr(self,sid)
759            student.manage_setLocalRoles(sid, ['Owner',])
760            student.invokeFactory('StudentApplication','application')
761            da = {'Title': 'Application Data'}
762            da["jamb_reg_no"] = jamb.get("REG-NO")
763            da["jamb_lastname"] = jamb_name
764            da["jamb_sex"] = jamb.get("SEX")
765            da["jamb_state"] = jamb.get("STATE")
766            da["jamb_lga"] = jamb.get("LGA")
767            da["jamb_score"] = jamb.get("AGGREGATE")
768            da["jamb_first_cos"] = jamb.get("COURSE1")
769            da["jamb_second_cos"] = jamb.get("COURSE2")
770            da["jamb_first_uni"] = jamb.get("UNIV1")
771            da["jamb_second_uni"] = jamb.get("UNIV2")
772            app = student.application
773            app_doc = app.getContent()
774            app_doc.edit(mapping=da)
775            #wftool.doActionFor(app,'open',dest_container=app)
776            app.manage_setLocalRoles(sid, ['Owner',])
777            student.getContent().createSubObjects()
778        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
779    ###)
780
781
782    security.declareProtected(View,"fixOwnership")
783    def fixOwnership(self):
784        """fix Ownership"""
785        for s in self.portal_catalog(meta_type = 'Student'):
786            student = s.getObject()
787            sid = s.getId
788            import pdb;pdb.set_trace()
789            student.application.manage_setLocalRoles(sid, ['Owner',])
790            student.personal.manage_setLocalRoles(sid, ['Owner',])
791
792    security.declareProtected(View,"Title")
793    def Title(self):
794        """compose title"""
795        return "Student Section"
796
797    def generateStudentId(self,letter): ###(
798        import random
799        r = random
800        if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
801            letter= r.choice('ABCDEFGHKLMNPQRSTUVWXY')
802        students = self.portal_catalog(meta_type = "StudentsFolder")[-1]
803        sid = "%c%d" % (letter,r.randint(99999,1000000))
804        while hasattr(students, sid):
805            sid = "%c%d" % (letter,r.randint(99999,1000000))
806        return sid
807        #return "%c%d" % (r.choice('ABCDEFGHKLMNPQRSTUVWXY'),r.randint(99999,1000000))
808    ###)
809
810InitializeClass(StudentsFolder)
811
812def addStudentsFolder(container, id, REQUEST=None, **kw):
813    """Add a Student."""
814    ob = StudentsFolder(id, **kw)
815    return CPSBase_adder(container, ob, REQUEST=REQUEST)
816###)
817
818class Student(CPSDocument): ###(
819    """
820    WAeUP Student container for the various student data
821    """
822    meta_type = 'Student'
823    portal_type = meta_type
824    security = ClassSecurityInfo()
825
826    security.declareProtected(View,"Title")
827    def Title(self):
828        """compose title"""
829        reg_nr = self.getId()[1:]
830        data = getattr(self,'personal',None)
831        if data:
832            content = data.getContent()
833            return "%s %s" % (content.firstname,content.lastname)
834        data = getattr(self,'application',None)
835        if data:
836            content = data.getContent()
837            return "%s" % (content.jamb_lastname)
838        return self.title
839
840    security.declarePrivate('makeStudentMember') ###(
841    def makeStudentMember(self,sid,password='uNsEt'):
842        """make the student a member"""
843        membership = self.portal_membership
844        membership.addMember(sid,
845                             password ,
846                             roles=('Member',
847                                     'Student',
848                                     ),
849                             domains='',
850                             properties = {'memberareaCreationFlag': False,
851                                           'homeless': True},)
852        member = membership.getMemberById(sid)
853        self.portal_registration.afterAdd(member, sid, password, None)
854        self.manage_setLocalRoles(sid, ['Owner',])
855
856###)
857
858    security.declareProtected(View,'createSubObjects') ###(
859    def createSubObjects(self):
860        """make the student a member"""
861        dp = {'Title': 'Personal Data'}
862        app_doc = self.application.getContent()
863        names = app_doc.jamb_lastname.split()
864        if len(names) == 3:
865            dp['firstname'] = names[0].capitalize()
866            dp['middlename'] = names[1].capitalize()
867            dp['lastname'] = names[2].capitalize()
868        elif len(names) == 2:
869            dp['firstname'] = names[0].capitalize()
870            dp['lastname'] = names[1].capitalize()
871        else:
872            dp['lastname'] = app_doc.jamb_lastname
873        dp['sex'] = app_doc.jamb_sex == 'F'
874        dp['lga'] = "%s/%s" % (app_doc.jamb_state,app_doc.jamb_lga )
875        proxy = self.aq_parent
876        proxy.invokeFactory('StudentPersonal','personal')
877        per = proxy.personal
878        per_doc = per.getContent()
879        per_doc.edit(mapping = dp)
880        per.manage_setLocalRoles(proxy.getId(), ['Owner',])
881        #self.portal_workflow.doActionFor(per,'open',dest_container=per)
882
883###)
884
885InitializeClass(Student)
886
887def addStudent(container, id, REQUEST=None, **kw):
888    """Add a Student."""
889    ob = Student(id, **kw)
890    return CPSBase_adder(container, ob, REQUEST=REQUEST)
891
892###)
893
894class StudentAccommodation(CPSDocument): ###(
895    """
896    WAeUP Student container for the various student data
897    """
898    meta_type = 'StudentAccommodation'
899    portal_type = meta_type
900    security = ClassSecurityInfo()
901
902    security.declareProtected(View,"Title")
903    def Title(self):
904        """compose title"""
905        content = self.getContent()
906        #return "Accommodation Data for %s %s" % (content.firstname,content.lastname)
907        return "Accommodation Data for Session %s" % content.session
908
909
910InitializeClass(StudentAccommodation)
911
912def addStudentAccommodation(container, id, REQUEST=None, **kw):
913    """Add a Students personal data."""
914    ob = StudentAccommodation(id, **kw)
915    return CPSBase_adder(container, ob, REQUEST=REQUEST)
916
917###)
918
919class StudentPersonal(CPSDocument): ###(
920    """
921    WAeUP Student container for the various student data
922    """
923    meta_type = 'StudentPersonal'
924    portal_type = meta_type
925    security = ClassSecurityInfo()
926
927    security.declareProtected(View,"Title")
928    def Title(self):
929        """compose title"""
930        content = self.getContent()
931        #return "Personal Data for %s %s" % (content.firstname,content.lastname)
932        return "Personal Data"
933
934
935InitializeClass(StudentPersonal)
936
937def addStudentPersonal(container, id, REQUEST=None, **kw):
938    """Add a Students personal data."""
939    ob = StudentPersonal(id, **kw)
940    return CPSBase_adder(container, ob, REQUEST=REQUEST)
941
942###)
943
944class StudentClearance(CPSDocument): ###(
945    """
946    WAeUP Student container for the various student data
947    """
948    meta_type = 'StudentClearance'
949    portal_type = meta_type
950    security = ClassSecurityInfo()
951
952    security.declareProtected(View,"Title")
953    def Title(self):
954        """compose title"""
955        content = self.getContent()
956        #return "Clearance/Eligibility Record for %s %s" % (content.firstname,content.lastname)
957        return "Clearance/Eligibility Record"
958
959
960InitializeClass(StudentClearance)
961
962def addStudentClearance(container, id, REQUEST=None, **kw):
963    """Add a Students personal data."""
964    ob = StudentClearance(id, **kw)
965    return CPSBase_adder(container, ob, REQUEST=REQUEST)
966
967###)
968
969class StudentStudyLevel(CPSDocument): ###(
970    """
971    WAeUP Student container for the various student data
972    """
973    meta_type = 'StudentStudyLevel'
974    portal_type = meta_type
975    security = ClassSecurityInfo()
976
977    security.declareProtected(View,"Title")
978    def Title(self):
979        """compose title"""
980        return "Level %s" % self.aq_parent.getId()
981
982##    security.declarePublic("gpa")
983##    def gpa(self):
984##        """calculate the gpa"""
985##        sum = 0
986##        course_count = 0
987##        for sc in self.objectValues():
988##            result = sc.getContent()
989##            if not result.grade:
990##                continue
991##            res = self.portal_catalog({'meta_type': 'Course',
992##                                          'id': sc.aq_parent.id})
993##            if len(res) != 1:
994##                continue
995##            course = res[0].getObject().getContent()
996##            sum += course.credits * ['F','E','D','C','B','A'].index(result.grade)
997##            course_count += 1
998##        if course_count:
999##            return sum/course_count
1000##        return 0.0
1001
1002InitializeClass(StudentStudyLevel)
1003
1004def addStudentStudyLevel(container, id, REQUEST=None, **kw):
1005    """Add a Students personal data."""
1006    ob = StudentStudyLevel(id, **kw)
1007    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1008
1009###)
1010
1011class StudentStudyCourse(CPSDocument): ###(
1012    """
1013    WAeUP Student container for the various student data
1014    """
1015    meta_type = 'StudentStudyCourse'
1016    portal_type = meta_type
1017    security = ClassSecurityInfo()
1018
1019    security.declareProtected(View,"Title")
1020    def Title(self):
1021        """compose title"""
1022        content = self.getContent()
1023        return "Study Course"
1024
1025
1026InitializeClass(StudentStudyCourse)
1027
1028def addStudentStudyCourse(container, id, REQUEST=None, **kw):
1029    """Add a Students personal data."""
1030    ob = StudentStudyCourse(id, **kw)
1031    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1032
1033###)
1034
1035class StudentApplication(CPSDocument): ###(
1036    """
1037    WAeUP Student container for the various student data
1038    """
1039    meta_type = 'StudentApplication'
1040    portal_type = meta_type
1041    security = ClassSecurityInfo()
1042
1043    security.declareProtected(View,"Title")
1044    def Title(self):
1045        """compose title"""
1046        return "Application Data"
1047
1048
1049InitializeClass(StudentApplication)
1050
1051def addStudentApplication(container, id, REQUEST=None, **kw):
1052    """Add a Students eligibility data."""
1053    ob = StudentApplication(id, **kw)
1054    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1055###)
1056
1057
1058class StudentPume(CPSDocument): ###(
1059    """
1060    WAeUP Student container for the various student data
1061    """
1062    meta_type = 'StudentPume'
1063    portal_type = meta_type
1064    security = ClassSecurityInfo()
1065
1066    security.declareProtected(View,"Title")
1067    def Title(self):
1068        """compose title"""
1069        return "PUME Results"
1070
1071
1072InitializeClass(StudentPume)
1073
1074def addStudentPume(container, id, REQUEST=None, **kw):
1075    """Add a Students PUME data."""
1076    ob = StudentPume(id, **kw)
1077    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1078###)
1079
1080##class StudentSemester(CPSDocument): ###(
1081##    """
1082##    WAeUP StudentSemester containing the courses and students
1083##    """
1084##    meta_type = 'StudentSemester'
1085##    portal_type = meta_type
1086##    security = ClassSecurityInfo()
1087##
1088##InitializeClass(StudentSemester)
1089##
1090##def addStudentSemester(container, id, REQUEST=None, **kw):
1091##    """Add a StudentSemester."""
1092##    ob = StudentSemester(id, **kw)
1093##    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1094##
1095#####)
1096
1097##class Semester(CPSDocument): ###(
1098##    """
1099##    WAeUP Semester containing the courses and students
1100##    """
1101##    meta_type = 'Semester'
1102##    portal_type = meta_type
1103##    security = ClassSecurityInfo()
1104##
1105##InitializeClass(Semester)
1106##
1107##def addSemester(container, id, REQUEST=None, **kw):
1108##    """Add a Semester."""
1109##    ob = Semester(id, **kw)
1110##    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1111##
1112#####)
1113
1114class StudentCourseResult(CPSDocument): ###(
1115    """
1116    WAeUP StudentCourseResult
1117    """
1118    meta_type = 'StudentCourseResult'
1119    portal_type = meta_type
1120    security = ClassSecurityInfo()
1121
1122    def getCourseEntry(self,cid):
1123        res = self.portal_catalog({'meta_type': "Course",
1124                                           'id': cid})
1125        if res:
1126            return res[-1]
1127        else:
1128            return None
1129
1130    security.declareProtected(View,"Title")
1131    def Title(self):
1132        """compose title"""
1133        cid = self.aq_parent.getId()
1134        ce = self.getCourseEntry(cid)
1135        if ce:
1136            return "%s" % ce.Title
1137        return "No course with id %s" % cid
1138
1139InitializeClass(StudentCourseResult)
1140
1141def addStudentCourseResult(container, id, REQUEST=None, **kw):
1142    """Add a StudentCourseResult."""
1143    ob = StudentCourseResult(id, **kw)
1144    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1145###)
1146
1147# Backward Compatibility StudyLevel
1148
1149from Products.WAeUP_SRP.Academics import StudyLevel
1150
1151from Products.WAeUP_SRP.Academics import addStudyLevel
1152
Note: See TracBrowser for help on using the repository browser.