source: WAeUP_SRP/trunk/Students.py @ 2026

Last change on this file since 2026 was 2016, checked in by Henrik Bettermann, 17 years ago

again some changes in exportStudents (according to ticket #276)

  • Property svn:keywords set to Id
File size: 67.2 KB
Line 
1#-*- mode: python; mode: fold -*-
2# $Id: Students.py 2016 2007-07-13 21:56:40Z henrik $
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
18from Products.AdvancedQuery import Eq, Between, Le,In
19import DateTime
20import logging
21import csv,re,os
22import Globals
23p_home = Globals.package_home(globals())
24i_home = Globals.INSTANCE_HOME
25MAX_TRANS = 1000
26from urllib import urlencode
27
28import DateTime
29#import PIL.Image
30from StringIO import StringIO
31
32def makeCertificateCode(code): ###(
33    code = code.replace('.','')
34    code = code.replace('(','')
35    code = code.replace(')','')
36    code = code.replace('/','')
37    code = code.replace(' ','')
38    code = code.replace('_','')
39    return code
40
41###)
42
43def response_write(response,s): ###(
44    response.setHeader('Content-type','text/html; charset=ISO-8859-15')
45    while s.find('<') > -1:
46        s = s.replace('<','&lt;')
47    while s.find('>') > -1:
48        #from pdb import set_trace;set_trace()
49        s = s.replace('>','&gt;')
50    response.write("%s<br>\n" % s)
51
52###)
53
54def getInt(s): ###(
55    try:
56        return int(s)
57    except:
58        return 0
59
60def getFloat(s):
61    try:
62        return float(s)
63    except:
64        return 0.0
65
66###)
67
68def getStudentByRegNo(self,reg_no): ###(
69    """search student by JAMB Reg No and return StudentFolder"""
70    res = self.students_catalog(jamb_reg_no = reg_no.upper())
71    if len(res) == 1:
72        return getattr(self.portal_url.getPortalObject().campus.students,res[0].id)
73    else:
74        return None
75    # don't search in portal_catalog
76    # search = ZCatalog.searchResults(self.portal_catalog_real,{'meta_type': 'StudentApplication',
77    #                               'SearchableText': reg_no,
78    #                               })
79    # if len(search) < 1:
80    #     return None
81    # return search[0].getObject().aq_parent
82
83###)
84
85def checkJambNo(jnr): ###(
86    try:
87        if len(jnr) != 10:
88            return False
89    except:
90        return False
91    try:
92        int(jnr[:8])
93        return True
94    except:
95        return False
96
97###)
98
99def formatLGA(lga):
100    if lga.find('_') > -1:
101        lgadic = lga.split('_')
102        return lgadic[0].upper(),lgadic[1].upper()
103    return "",lga
104
105class StudentsFolder(CPSDocument): ###(
106    """
107    WAeUP container for the various WAeUP containers data
108    """
109    meta_type = 'StudentsFolder'
110    portal_type = meta_type
111    security = ClassSecurityInfo()
112
113    security.declareProtected(ModifyPortalContent,"loadPumeResultsFromCSV")###(
114    def loadPumeResultsFromCSV(self):
115        """load Fulltime Studentdata from CSV values into pumeresults catalog"""
116        import transaction
117        import random
118##        csv_d = {'jamb_reg_no': "RegNumber", ###(
119##                 'status': "Admission Status",
120##                 'name': "Name",
121##                 'score': "Score",
122##                 'sex': "Sex",
123##                 'faculty': "Faculty",
124##                 'department': "Dept",
125##                 'course': "Course",
126##                 'course_code_org': "Course Code",
127##                 }
128###)
129##        csv_d = {'jamb_reg_no': "JAMBRegno",
130##                'name': "Name",
131##                'score': "Score",
132##                 'sex': "Sex",
133##                 'course': "Course",
134##                 'faculty': "Faculty",
135##                 'department': "Dept",
136##                 'course_code_org': "Course Code",
137##                 'status': "Admission Status",
138##                 'result_type': None,
139##                 }
140
141        csv_d = {'jamb_reg_no': "reg_no",
142                 'name': "fullname",
143                 'score': "pume_score",
144                 'sex': "sex",
145                 'course': "study_course",
146                 'course_code_org': "study_course",
147                 'status': "admission_status",
148                 'result_type': "entry_mode",
149                 }
150
151        csv_fields = [f[1] for f in csv_d.items() if f[1]]
152        tr_count = 0
153        total = 0
154        #name = 'pup_new'
155        #name = 'pup_update'
156        name = 'Admitted_update'
157        update = name.endswith('update')
158        no_import = []
159        ok_import = []
160        ok_import.append('%s' % ','.join(['"%s"' % fn for fn in csv_d.keys()]))
161        no_import.append('%s' % ','.join(['"%s"' % fn for fn in csv_fields]))
162        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
163        ok_import_name = "%s/import/%s_imported_%s.csv" % (i_home,name,current)
164        #open(ok_import_name,"w").write('\n'.join(no_import))
165        no_import_name = "%s/import/%s_not_imported_%s.csv" % (i_home,name,current)
166        #open(no_import_name,"w").write('\n'.join(no_import))
167        logger = logging.getLogger('Students.loadPumeResultsFromCSV')
168        starttime = DateTime.now()
169        logger.info('Start loading from %s.csv' % name)
170        try:
171            result = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
172        except:
173            logger.error('Error reading %s.csv' % name)
174            return
175        pume = self.portal_pumeresults
176        format = ','.join(['"%%(%s)s"' % fn for fn in csv_fields])
177        import_format = ','.join(['"%%(%s)s"' % fn for fn in csv_d.keys()])
178        eduplicate = '%s,"duplicate"' % format
179        eoriginal = '%s,"original"' % format
180        einvalidjamb = '%s,"invalid JambRegNo"' % format
181        added = 'added ,%s' % format
182        #from pdb import set_trace;set_trace()
183        for jamb in result:
184            if not jamb.get(csv_d['score']):
185                logger.info('Student %s has no pume_score' % jamb.get(csv_d['jamb_reg_no']))
186                continue
187            dict = {}
188            for f,fn in csv_d.items():
189                dict[f] = jamb.get(csv_d[f])
190            dict['result_type'] = 'CEST'
191            jnr = jamb.get(csv_d['jamb_reg_no'])
192            #if not checkJambNo(jnr):
193            #    logger.info(einvalidjamb % jamb)
194            #    dd = {}
195            #    for f,fn in csv_d.items():
196            #        dd[fn] = getattr(data,f)
197            #        no_import.append(eduplicate % dd)
198            #        no_import.append(eduplicate % jamb)
199            #    continue
200            res = pume(jamb_reg_no=jnr)
201            if len(res) > 0:
202                if update:
203                    try:
204                        pume.modifyRecord(**dict)
205                    # Can not happen, but anyway...
206                    except ValueError:
207                        logger.info(eduplicate % jamb)
208                        continue
209                    # Can not happen, but anyway...
210                    except KeyError:
211                        pume.addRecord(**dict)
212                        logger.info(added % jamb)
213                        continue
214                else:
215                    data = res[0]
216                    if data.name != jamb.get(csv_d['name']):
217                        #set_trace()
218                        logger.info(eduplicate % jamb)
219                        #em = 'Student with REG-NO %(jamb_reg_no)s already exists\n' % dict
220                        #logger.info(em)
221                        dd = {}
222                        for f,fn in csv_d.items():
223                            dd[fn] = getattr(data,f)
224                        no_import.append(eoriginal % dd)
225                        no_import.append(eduplicate % jamb)
226                    continue
227            else:
228                try:
229                    pume.addRecord(**dict)
230                    ok_import.append(import_format % dict)
231                except ValueError:
232                    logger.info(eduplicate % jamb)
233                    #em = 'Student with REG-NO %(jamb_reg_no)s already exists\n' % dict
234                    #logger.info(em)
235                    no_import.append(eduplicate % jamb)
236        logger.info('End loading from %s.csv' % name)
237        if len(no_import) > 1:
238            open(no_import_name,"w+").write('\n'.join(no_import))
239        open(ok_import_name,"w+").write('\n'.join(ok_import))
240        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
241    ###)
242
243    security.declareProtected(ModifyPortalContent,"createStudents")###(
244    def createStudents(self):
245        """
246        load addmitted Studentdata from CSV values and create Studentobjects.
247        This is the current method to create new addmitted Students.
248        Before running the eventservice for the students_catalog must be disabled.
249        """
250        import transaction
251        import random
252        #from pdb import set_trace
253        wftool = self.portal_workflow
254        #students_folder = self.portal_catalog({'meta_type': 'StudentsFolder'})[-1].getObject()
255        students_folder = self.portal_url.getPortalObject().campus.students
256        levels =       {'ume_ft':'100',
257                        'de_ft': '200',
258                        'ug_pt': '100',
259                        'de_pt': '200',
260                        'pg_ft': '700',
261                        'pg_pt': '700',
262                        'dp_pt': '100',
263                        'dp_ft': '100',
264                        }
265        csv_d = {'jamb_reg_no': "reg_no",
266                 'entry_mode': 'entry_mode',
267                 'jamb_firstname': "firstname",
268                 'jamb_middlename': "middlename",
269                 'jamb_lastname': "lastname",
270                 'jamb_sex': "sex",
271                 'jamb_state': "state",
272                 'birthday': "date_of_birth",
273                 'app_email': "email",
274                 'study_course': "study_course",
275                 'perm_address': "address",
276                 'admission_status': "admission_status",
277                 }
278        csv_fields = [f[1] for f in csv_d.items()]
279        tr_count = 0
280        total = 0
281        #name = 'pume_results'
282        name = 'Admitted_update'
283        no_import = []
284        s = ','.join(['"%s"' % fn for fn in csv_fields])
285        no_import.append('"Error",%s' % s)
286        format = '"%(Error)s",' + ','.join(['"%%(%s)s"' % fn for fn in csv_fields])
287        no_certificate = "no certificate %s" % format
288        open("%s/import/%s_not_imported.csv" % (i_home,name),"w").write('\n'.join(no_import))
289        logger = logging.getLogger('Students.StudentsFolder.createStudents')
290        logger.info('Start loading from %s.csv' % name)
291        certs = {}
292        try:
293            results = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
294        except:
295            logger.error('Error reading %s.csv' % name)
296            return
297        for result in results:
298            if not result.get(csv_d['admission_status']).startswith('Admitted'):
299                continue
300            #result['Error'] = "Processing "
301            #logger.info(format % result)
302            jamb_reg_no = result.get(csv_d['jamb_reg_no'])
303            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
304            if res:
305                em = 'Student with RegNo %s already exists\n' % jamb_reg_no
306                logger.info(em)
307                result['Error'] = "Student exists"
308                no_import.append(format % result)
309                continue
310            cert_id = makeCertificateCode(result.get(csv_d['study_course']))
311            if cert_id not in certs.keys():
312                res = self.portal_catalog(meta_type = "Certificate",id = cert_id)
313                if not res:
314                    em = 'No Certificate with ID %s \n' % cert_id
315                    logger.info(em)
316                    result['Error'] = "No Certificate %s" % cert_id
317                    no_import.append( format % result)
318                    continue
319                cert = res[0]
320                cert_path = cert.getPath().split('/')
321                certificate = certs[cert_id] = {'faculty': cert_path[-4],
322                                     'department': cert_path[-3]}
323            cert_doc = certs[cert_id]
324            catalog_entry = {}
325            catalog_entry['jamb_reg_no'] = jamb_reg_no
326            firstname = result.get(csv_d['jamb_firstname'])
327            middlename = result.get(csv_d['jamb_middlename'])
328            lastname = result.get(csv_d['jamb_lastname'])
329            if len(firstname) < 3\
330               and len(middlename) < 3\
331               and len(lastname) < 3:
332                em = 'Student Names to short \n'
333                logger.info(em)
334                result['Error'] = "Names to short"
335                no_import.append( format % result)
336                continue
337            perm_address = result.get(csv_d['perm_address'])
338            sid = self.generateStudentId('x')
339            students_folder.invokeFactory('Student', sid)
340            catalog_entry['id'] = sid
341            tr_count += 1
342            logger.info('%(total)s+%(tr_count)s: Creating Student with ID %(sid)s reg_no %(jamb_reg_no)s ' % vars())
343            student = getattr(self,sid)
344            student.manage_setLocalRoles(sid, ['Owner',])
345            student.invokeFactory('StudentApplication','application')
346            da = {'Title': 'Application Data'}
347            da["jamb_firstname"] = firstname
348            da["jamb_middlename"] = middlename
349            da["jamb_lastname"] = lastname
350            catalog_entry['entry_session'] = da["entry_session"] = self.getSessionId()[-2:]
351            catalog_entry['sex'] = sex = result.get(csv_d['jamb_sex']).startswith('F')
352            da_fields = ('jamb_reg_no',
353                         'jamb_sex',
354                         'jamb_state',
355                         'entry_mode',
356                         'app_email',
357                         )
358            for f in da_fields:
359                da[f] = result.get(csv_d[f])
360            catalog_entry['email'] = da['app_email']
361            catalog_entry['entry_mode'] = da['entry_mode']
362            app = student.application
363            app_doc = app.getContent()
364            app.getContent().edit(mapping=da)
365            picture ="%s/import/pictures/%s.jpg" % (i_home,jamb_reg_no)
366            app.manage_setLocalRoles(sid, ['Owner',])
367
368            picture_id = da['jamb_reg_no'].replace('/','_')
369            file = None
370            for ext in ('jpg','JPG'):
371                picture ="%s/import/pictures_admitted_latest/%s.%s" % (i_home,picture_id,ext)
372                if os.path.exists(picture):
373                    file = open(picture)
374                    break
375            if file is not None:
376
377                ## file conversion does not work
378                #img = PIL.Image.open(file)
379                #img.thumbnail((150,200),
380                #              resample=PIL.Image.ANTIALIAS)
381                #outfile = StringIO()
382                #img.save(outfile, format=img.format)
383
384                outfile = file.read()
385                app_doc.manage_addFile('passport',
386                                       file=outfile,
387                                       title="%s.jpg" % jamb_reg_no)
388            #wftool.doActionFor(app,'close')
389            dp = {}
390            dp['firstname'] = firstname
391            dp['middlename'] = middlename
392            dp['lastname'] = lastname
393            dp['email'] = da['app_email']
394            dp['sex'] = sex
395            dp['perm_address'] = perm_address
396            catalog_entry['name'] = "%(firstname)s %(middlename)s %(lastname)s" % dp
397            student.invokeFactory('StudentPersonal','personal')
398            per = student.personal
399            per_doc = per.getContent()
400            per_doc.edit(mapping = dp)
401            per.manage_setLocalRoles(sid, ['Owner',])
402            wftool.doActionFor(student,'pume_pass')
403            wftool.doActionFor(student,'admit')
404            #
405            # Clearance
406            #
407            student.invokeFactory('StudentClearance','clearance')
408            #wftool.doActionFor(student.clearance,'open')
409            clearance = student.clearance
410            dc = {'Title': 'Clearance/Eligibility Record'}
411            clearance = student.clearance
412            date_str = result.get(csv_d['birthday'])
413            try:
414                date = DateTime.DateTime(date_str)
415            except:
416                #import pdb;pdb.set_trace()
417                date = None
418            dc['birthday'] = date
419            clearance.getContent().edit(mapping=dc)
420            clearance.manage_setLocalRoles(sid, ['Owner',])
421            #
422            # Study Course
423            #
424            student.invokeFactory('StudentStudyCourse','study_course')
425            study_course = student.study_course
426            dsc = {}
427            catalog_entry['level'] = dsc['current_level'] = levels.get(da['entry_mode'],'100')
428            #catalog_entry['level'] = dsc['current_level'] = '100'  # Attention: not for DE students
429            catalog_entry['session'] = dsc['current_session'] = da['entry_session']
430            catalog_entry['mode'] = dsc['current_mode'] = da['entry_mode']
431            catalog_entry['course'] = dsc['study_course'] = cert_id
432            catalog_entry['faculty'] = certificate['faculty']
433            catalog_entry['department'] = certificate['department']
434            catalog_entry['verdict'] = dsc['current_verdict'] = 'N/A'
435            catalog_entry['review_state'] = self.portal_workflow.getInfoFor(student,'review_state',None)
436            study_course.getContent().edit(mapping=dsc)
437            #import pdb;pdb.set_trace()
438            self.students_catalog.addRecord(**catalog_entry)
439            if tr_count > 100:
440                if len(no_import) > 0:
441                    open("%s/import/%s_not_imported.csv" % (i_home,name),"a").write(
442                             '\n'.join(no_import) + "\n")
443                    no_import = []
444                em = '%d transactions commited\n' % tr_count
445                transaction.commit()
446                logger.info(em)
447                total += tr_count
448                tr_count = 0
449        open("%s/import/%s_not_imported.csv" % (i_home,name),"a").write(
450                                                '\n'.join(no_import))
451        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
452    ###)
453
454    security.declareProtected(ModifyPortalContent,"transferStudents")###(
455    def transferStudents(self,filename):
456        """
457        load Interfaculty transferStudents Studentdata from CSV values.
458        """
459        import transaction
460        import random
461        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
462        pm = self.portal_membership
463        member = pm.getAuthenticatedMember()
464        logger = logging.getLogger('Students.StudentsFolder.transferStudents')
465        #students_folder = self.portal_catalog({'meta_type': 'StudentsFolder'})[-1].getObject()
466        students_folder = self.portal_url.getPortalObject().campus.students
467        csv_fields = ('old_matric_no',
468                      'matric_no',
469                      'study_course',
470                      'current_mode',
471                      'current_level',
472                      )
473        tr_count = 0
474        total = 0
475        total_imported = 0
476        total_not_imported = 0
477        imported = []
478        not_imported = []
479        certs = {}
480        try:
481            results = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
482        except:
483            logger.error('Error reading %s.csv' % filename)
484            return
485        start = True
486        for result in results:
487            total += 1
488            if start:
489                start = False
490                logger.info('%s starts import from %s.csv' % (member,filename))
491                import_keys = [k for k in result.keys() if not k.startswith('ignore')]
492                diff2schema = set(import_keys).difference(set(csv_fields))
493                if diff2schema:
494                    em = "not ignorable key(s) %s found in heading" % diff2schema
495                    return em
496                s = ','.join(['"%s"' % fn for fn in import_keys])
497                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(s + ',"Error"'+ '\n')
498                s = '"id",' + s
499                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
500                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
501                format_error = format + ',"%(Error)s"'
502                format = '"%(id)s",'+ format
503            old_matric_no = result.get('old_matric_no')
504            res = self.students_catalog(matric_no = old_matric_no)
505            result['id'] = "None"
506            if not res:
507                em = 'Student with matric_no %s not found' % old_matric_no
508                logger.info(em)
509                result['Error'] = "Student does not exist"
510                not_imported.append(format_error % result)
511                total_not_imported += 1
512                continue
513            student_brain = res[0]
514            student_object = getattr(students_folder,student_brain.id)
515            result['id'] = student_brain.id
516            cert_id = makeCertificateCode(result.get('study_course'))
517            if cert_id not in certs.keys():
518                res = self.portal_catalog(meta_type = "Certificate",id = cert_id)
519                if not res:
520                    em = 'No certificate with ID %s \n' % cert_id
521                    logger.info(em)
522                    result['Error'] = "No Certificate %s" % cert_id
523                    not_imported.append( format_error % result)
524                    total_not_imported += 1
525                    continue
526                cert = res[0]
527                cert_path = cert.getPath().split('/')
528                certificate = certs[cert_id] = {'faculty': cert_path[-4],
529                                     'department': cert_path[-3]}
530            cert_doc = certs[cert_id]
531            clearance = getattr(student_object,'clearance',None)
532            if clearance is None:
533                em = 'Student has no clearance object'
534                logger.info(em)
535                result['Error'] = em
536                not_imported.append( format_error % result)
537                total_not_imported += 1
538                continue
539            clearance_doc = clearance.getContent()
540            study_course = student_object.study_course
541            study_course_doc = study_course.getContent()
542            old_study_course = study_course_doc.study_course
543            old_current_level = study_course_doc.current_level
544            current_level = result.get('current_level',None)
545            new_study_course = result.get('study_course',None)
546            try:
547                icl = int(current_level)
548            except:
549                em = 'Invalid new level %s' % current_level
550                logger.info(em)
551                result['Error'] = em
552                not_imported.append( format_error % result)
553                total_not_imported += 1
554                continue
555            if icl == int(old_current_level) and old_study_course == new_study_course:
556                em = 'Already transferred'
557                logger.info(em)
558                result['Error'] = em
559                not_imported.append( format_error % result)
560                total_not_imported += 1
561                continue
562            if study_course.objectIds():
563                em = 'Already registered level %s for %s, but is supposed to study %s at level %s' % (old_current_level,old_study_course,new_study_course,current_level)
564                logger.info(em)
565                result['Error'] = em
566                not_imported.append( format_error % result)
567                total_not_imported += 1
568                continue
569            #from pdb import set_trace; set_trace()
570            cd = {}
571            matric_no_history = getattr(clearance_doc,'matric_no_history',[])
572            if not matric_no_history:
573                matric_no_history = []
574            matric_no_history.append(old_matric_no)
575            cd['matric_no_history'] = matric_no_history
576            cd['matric_no'] = result.get('matric_no')
577            clearance_doc.edit(mapping = cd)
578            dsc = {}
579            study_course_history = getattr(study_course_doc,'study_course_history',[])
580            if not study_course_history:
581                study_course_history = []
582            study_course_history.append(old_study_course)
583            dsc['study_course_history'] = study_course_history
584            dsc['study_course'] = new_study_course
585            dsc['current_level'] = current_level
586            dsc['current_mode'] = result.get('current_mode')
587            study_course_doc.edit(mapping=dsc)
588            imported.append( format % result)
589            tr_count += 1
590            total_imported += 1
591            if tr_count > 1000:
592                if len(not_imported) > 0:
593                    open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
594                             '\n'.join(not_imported) + '\n')
595                    not_imported = []
596                if len(imported) > 0:
597                    open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
598                             '\n'.join(imported) + '\n')
599                    imported = []
600                em = '%d transactions committed\n' % (tr_count)
601                transaction.commit()
602                regs = []
603                logger.info(em)
604                tr_count = 0
605        if len(imported) > 0:
606            open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
607                                                '\n'.join(imported))
608        if len(not_imported) > 0:
609            open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
610                                                '\n'.join(not_imported))
611        em = "Imported: %d, not imported: %d of total %d" % (total_imported,total_not_imported,total)
612        logger.info(em)
613        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
614    ###)
615
616    security.declareProtected(ModifyPortalContent,"importReturningStudents")###(
617    def importReturningStudents(self):
618        """load Returning Studentdata from CSV values"""
619        import transaction
620        import random
621        #from pdb import set_trace
622        wftool = self.portal_workflow
623        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
624        #students_folder = self.portal_catalog({'meta_type': 'StudentsFolder'})[-1].getObject()
625        students_folder = self.portal_url.getPortalObject().campus.students
626        tr_count = 1
627        total = 0
628        #name = 'pume_results'
629        name = 'Returning'
630        table = self.returning_import
631        no_import = []
632        imported = []
633        logger = logging.getLogger('Students.StudentsFolder.importReturningStudents')
634        try:
635            returning = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
636        except:
637            logger.error('Error reading %s.csv' % name)
638            return
639        l = self.portal_catalog({'meta_type': "Certificate"})
640        certs = {}
641        cert_docs = {}
642        for f in l:
643            certs[f.getId] = f.getObject().getContent()
644        start = True
645        res = table()
646        regs = []
647        if len(res) > 0:
648            regs = [s.matric_no for s in res]
649        #import pdb;pdb.set_trace()
650        for student in returning:
651            if start:
652                start = False
653                logger.info('Start loading from %s.csv' % name)
654                s = ','.join(['"%s"' % fn for fn in student.keys()])
655                imported.append(s)
656                no_import.append('%s,"Error"' % s)
657                format = ','.join(['"%%(%s)s"' % fn for fn in student.keys()])
658                format_error = format + ',"%(Error)s"'
659                no_certificate = "no certificate %s" % format
660            student['matric_no'] = matric_no = student.get('matric_no').upper()
661            student['Mode_of_Entry'] = entry_mode = student.get('Mode of Entry').upper()
662            student['Permanent_Address'] = perm_address = student.get('Permanent Address')
663            if matric_no == '':
664                student['Error'] = "Empty matric_no"
665                no_import.append( format_error % student)
666                continue
667            if matric_no in regs or self.returning_import(matric_no = matric_no):
668                student['Error'] = "Duplicate"
669                no_import.append( format_error % student)
670                continue
671            cert_id = makeCertificateCode(student.get('Coursemajorcode'))
672            if cert_id not in certs.keys():
673                student['Error'] = "No Certificate %s" % cert_id
674                no_import.append( format_error % student)
675                continue
676            try:
677                table.addRecord(**student)
678            except ValueError:
679                student['Error'] = "Duplicate"
680                no_import.append( format_error % student)
681                continue
682            regs.append(student.get('matric_no'))
683            imported.append(format % student)
684            tr_count += 1
685            if tr_count > 1000:
686                if len(no_import) > 0:
687                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
688                             '\n'.join(no_import) + '\n')
689                    no_import = []
690                open("%s/import/%simported%s.csv" % (i_home,name,current),"a").write(
691                                            '\n'.join(no_import) + "\n")
692                imported = []
693                em = '%d transactions commited total %s\n' % (tr_count,total)
694                transaction.commit()
695                regs = []
696                logger.info(em)
697                total += tr_count
698                tr_count = 0
699        open("%s/import/%simported%s.csv" % (i_home,name,current),"a").write(
700                                            '\n'.join(imported))
701        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
702                                                '\n'.join(no_import))
703        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
704    ###)
705
706    security.declareProtected(ModifyPortalContent,"fixAllNames")###(
707    def fixAllNames(self):
708        "fix all students names"
709        import transaction
710        response = self.REQUEST.RESPONSE
711        logger = logging.getLogger('fixAllNames')
712        logger.info('Start')
713        students = self.portal_catalog(portal_type='Student')
714        count = 0
715        total = 0
716        for student in students:
717            scat_res = self.students_catalog(id = student.getId)
718            if not scat_res:
719                self.students_catalog.addRecord(id = student.getId)
720                scat_res = self.students_catalog(id = student.getId)
721            student_entry = scat_res[0]
722            old_new = self.fixName(student,student_entry)
723            count += 1
724            response_write(response,'"%d","%s",%s' % (count + total,student_entry.id,old_new))
725            if count > 2000:
726                transaction.commit()
727                logger.info("%d transactions commited" % count)
728                total += count
729                count = 0
730    ###)
731
732    security.declareProtected(ModifyPortalContent,"fixName")###(
733    def fixName(self,student_brain, student_entry):
734        "fix the name of a student"
735        fix = "first"
736        if student_entry.get('name_fixed',None) == fix:
737            return "Name already fixed"
738        student_id = student_entry.id
739        new_student = student_entry.jamb_reg_no.startswith('6')
740        student_obj = student_brain.getObject()
741        personal = getattr(student_obj,'personal',None)
742        invalid = ''
743        if personal is None:
744            return '"%s","Returning","%s","%s"' % (invalid,student_entry.name,"not logged in")
745        per_doc = personal.getContent()
746        old_first = per_doc.firstname
747        old_middle = per_doc.middlename
748        old_last = per_doc.lastname
749        new_first = ''
750        new_middle = ''
751        new_last = ''
752        if new_student:
753            if not old_first and not old_middle and old_last:
754                new_names = [n.capitalize() for n in old_last.split()]
755                if len(new_names) > 1:
756                    old_first = new_names[0]
757                    old_last = new_names[-1]
758                    old_middle = ' '.join(new_names[1:-1])
759                else:
760                    old_last = new_names[0]
761                    old_first = ''
762                    old_middle = ''
763            if old_first:
764                new_first = old_first
765            if old_middle:
766                new_middle = old_middle
767            if old_last:
768                new_last = old_last
769            if old_first.find('<') != -1 or\
770               old_first.find('>') != -1 or\
771               old_middle.find('<') != -1 or\
772               old_middle.find('>') != -1 or\
773               old_last.find('<') != -1 or\
774               old_last.find('>') != -1:
775                   invalid = "invalid characters"
776        else:
777            new_first = old_first
778            if new_first.strip() == '-':
779                new_first = ''
780            new_middle = old_middle
781            if new_middle.strip() == '-':
782                new_middle = ''
783            new_last = old_last
784            if new_last.strip() == '-':
785                new_last = ''
786        name = "%(new_first)s %(new_middle)s %(new_last)s" % vars()
787        if new_student:
788            text = "New"
789        else:
790            text = "Returning"
791        old_new = '"%s","%s","%s","%s"' % (invalid,text,
792                                           student_entry.name,
793                                           name)
794        if not invalid:
795            self.students_catalog.modifyRecord(id = student_id,
796                                      name_fixed = fix,
797                                      name = name)
798            per_doc.edit(mapping = {'firstname' : new_first,
799                                'middlename' : new_middle,
800                                'lastname' : new_last,
801                                })
802        return old_new
803    ###)
804
805    security.declareProtected(ModifyPortalContent,"updateReturningStudents")###(
806    def updateReturningStudents(self):
807        """load and overwrite Returning Student Data from CSV values"""
808        import transaction
809        import random
810        #from pdb import set_trace
811        wftool = self.portal_workflow
812        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
813        #students_folder = self.portal_catalog({'meta_type': 'StudentsFolder'})[-1].getObject()
814        students_folder = self.portal_url.getPortalObject().campus.students
815        tr_count = 1
816        total = 0
817        #name = 'pume_results'
818        name = 'Returning_update'
819        table = self.returning_import
820        no_import = []
821        imported = []
822        logger = logging.getLogger('Students.StudentsFolder.updateReturningStudents')
823        try:
824            returning = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
825        except:
826            logger.error('Error reading %s.csv' % name)
827            return
828        l = self.portal_catalog({'meta_type': "Certificate"})
829        certs = {}
830        cert_docs = {}
831        for f in l:
832            certs[f.getId] = f.getObject().getContent()
833        start = True
834        res = table()
835        regs = []
836        if len(res) > 0:
837            regs = [s.matric_no for s in res]
838        for student in returning:
839            if start:
840                start = False
841                logger.info('Start loading from %s.csv' % name)
842                s = ','.join(['"%s"' % fn for fn in student.keys()])
843                imported.append(s)
844                no_import.append('%s,"Error"' % s)
845                format = ','.join(['"%%(%s)s"' % fn for fn in student.keys()])
846                format_error = format + ',"%(Error)s"'
847                no_certificate = "no certificate %s" % format
848            matric_no = student.get('matric_no').upper()
849            student['matric_no'] = matric_no
850            if matric_no == '':
851                student['Error'] = "Empty matric_no"
852                no_import.append( format_error % student)
853                continue
854#            if matric_no in regs or self.returning_import(matric_no = matric_no):
855#                student['Error'] = "Duplicate"
856#                no_import.append( format_error % student)
857#                continue
858#            cert_id = makeCertificateCode(student.get('Coursemajorcode'))
859#            if cert_id not in certs.keys():
860#                student['Error'] = "No Certificate %s" % cert_id
861#                no_import.append( format_error % student)
862#                continue
863            try:
864                table.modifyRecord(**student)
865            except KeyError:
866                #import pdb;pdb.set_trace()
867                student['Error'] = "no Student found to update"
868                no_import.append( format_error % student)
869                continue
870            #s = self.students_catalog(matric_no=matric_no)
871            #if s:
872            #    level = "%s" % (int(student.get('Level')) + 100)
873            #    self.students_catalog.modifyRecord(id = s[0].id,
874            #                                           level=level)
875
876            regs.append(student.get('matric_no'))
877            imported.append(format % student)
878            tr_count += 1
879            if tr_count > 1000:
880                if len(no_import) > 0:
881                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
882                             '\n'.join(no_import) + '\n')
883                    no_import = []
884                open("%s/import/%simported%s.csv" % (i_home,name,current),"a").write(
885                                            '\n'.join(no_import) + "\n")
886                imported = []
887                em = '%d transactions commited total %s\n' % (tr_count,total)
888                transaction.commit()
889                regs = []
890                logger.info(em)
891                total += tr_count
892                tr_count = 0
893        open("%s/import/%simported%s.csv" % (i_home,name,current),"a").write(
894                                            '\n'.join(imported))
895        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
896                                                '\n'.join(no_import))
897        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
898    ###)
899
900    security.declareProtected(ModifyPortalContent,"exportStudents")###(
901    def exportStudents(self):
902        """export Studentsdata to a file"""
903        member = self.portal_membership.getAuthenticatedMember()
904        logger = logging.getLogger('Students.exportStudents')
905        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
906        students_folder = self.portal_url.getPortalObject().campus.students
907        export_file = "%s/export/students_%s.csv" % (i_home,current)
908
909        from Products.AdvancedQuery import Eq, Between, Le,In,MatchRegexp
910        aq_students = self.students_catalog.evalAdvancedQuery
911        toexport = {'students_catalog': ("id",
912                                         "matric_no",
913                                         "jamb_reg_no",
914                                         "name",
915                                         "review_state",
916                                         "entry_session",
917                                         "session",
918                                         "entry_mode",
919                                         "mode",
920                                         "verdict",
921                                         "sex",
922                                         "email",
923                                         "phone",
924                                         "faculty",
925                                         "department",
926                                         "course",
927                                         "level",
928                                        ),
929                    'personal': ('firstname',
930                                 'middlename',
931                                 'lastname',
932                                 'perm_address',
933                                 ),
934                    'clearance': ('state',  # is not an attribute of clearance but is needed for splitting lga
935                                  'lga',
936                                 )
937                  }
938        res_list = []
939        lines = []
940        fields = []
941        with_lga = False
942        for k in toexport.keys():
943            for f in toexport[k]:
944                if f == 'lga' :
945                    with_lga = True
946                fields.append(f)
947        headline = ','.join(fields).replace('level','current_level')
948        open(export_file,"a").write(headline +'\n')
949        format = '"%(' + ')s","%('.join(fields) + ')s"'
950        query = In('review_state',('cleared_and_validated',
951                                'clearance_requested',
952                                'school_fee_paid',
953                                'courses_registered',
954                                'courses_validated'))
955        #query = In('review_state',('clearance_requested'))
956        students = aq_students(query)
957        nr2export = len(students)
958        logger.info('%s starts exportStudents, %s student records to export' % (member,nr2export))
959        chunk = 1000
960        total = 0
961        start = DateTime.DateTime().timeTime()
962        start_chunk = DateTime.DateTime().timeTime()
963        ## alternative method slightly slower
964        # student_recs = {}
965        # for s in students:
966        #      student_recs[s.id] = s
967        # catalog_recs = {}
968        # brains = self.portal_catalog(portal_type = 'Student')
969        # for cat_rec in brains:
970        #     sid = cat_rec.getId
971        #     catalog_recs[sid] = cat_rec
972        # #import pdb;pdb.set_trace()
973        # start = DateTime.DateTime().timeTime()
974        # start_chunk = DateTime.DateTime().timeTime()
975        # for student in students:
976        #     if student.id not in student_recs.keys():
977        #         continue
978        #     not_all = False
979        #     d = self.getFormattedStudentEntry(student_recs[student.id])
980        #     student_obj = catalog_recs[student.id].getObject()
981        for student in students:
982            not_all = False
983            d = self.getFormattedStudentEntry(student)
984            student_obj = getattr(students_folder,student.id)
985            for k in toexport.keys()[1:]:
986                try:
987                    object = getattr(student_obj,k)
988                    object_doc = object.getContent()
989                except:
990                    logger.info('%s %s record not found' % (student.id,k))
991                    not_all = True
992                    continue
993                for f in toexport[k]:
994                    d[f] = getattr(object_doc,f,'')
995            if not_all:
996                continue
997            if with_lga:
998                d['state'],d['lga'] = formatLGA(d['lga'])
999            lines.append(format % d)
1000            total += 1
1001            if total and not total % chunk or total == len(students):
1002                open(export_file,"a").write('\n'.join(lines) +'\n')
1003                anz = len(lines)
1004                logger.info("wrote %(anz)d  total written %(total)d" % vars())
1005                end_chunk = DateTime.DateTime().timeTime()
1006                duration = end_chunk-start_chunk
1007                per_record = duration/anz
1008                till_now = end_chunk - start
1009                avarage_per_record = till_now/total
1010                estimated_end = DateTime.DateTime(start + avarage_per_record * nr2export)
1011                estimated_end = estimated_end.strftime("%H:%M:%S")
1012                logger.info('%(duration)4.1f, %(per_record)4.3f,end %(estimated_end)s' % vars())
1013                start_chunk = DateTime.DateTime().timeTime()
1014                lines = []
1015        end = DateTime.DateTime().timeTime()
1016        logger.info('total time %6.2f m' % ((end-start)/60))
1017        filename, extension = os.path.splitext(export_file)
1018        from subprocess import call
1019        msg = "wrote %(total)d records to %(export_file)s" % vars()
1020        try:
1021            retcode = call('gzip %s' % (export_file),shell=True)
1022            if retcode == 0:
1023                msg = "wrote %(total)d records to %(export_file)s.gz" % vars()
1024        except OSError, e:
1025            retcode = -99
1026            logger.info("zip failed with %s" % e)
1027        logger.info(msg)
1028        args = {'portal_status_message': msg}
1029        #url = self.REQUEST.get('URL1') + '?' + urlencode(args)
1030        url = self.REQUEST.get('URL2')
1031        return self.REQUEST.RESPONSE.redirect(url)
1032    ###)
1033
1034    security.declareProtected(ModifyPortalContent,"dumpStudentsCatalog")###(
1035    def dumpStudentsCatalog(self):
1036        """dump all data in students_catalog to a csv"""
1037        member = self.portal_membership.getAuthenticatedMember()
1038        logger = logging.getLogger('Students.dumpStudentsCatalog')
1039        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1040        export_file = "%s/export/students_catalog_%s.csv" % (i_home,current)
1041        res_list = []
1042        lines = []
1043        fields = []
1044        for f in self.students_catalog.schema():
1045            fields.append(f)
1046        headline = ','.join(fields)
1047        open(export_file,"a").write(headline +'\n')
1048        format = '"%(' + ')s","%('.join(fields) + ')s"'
1049        students = self.students_catalog()
1050        nr2export = len(students)
1051        logger.info('%s starts dumpStudentsCatalog, %s student records to export' % (member,nr2export))
1052        chunk = 2000
1053        total = 0
1054        start = DateTime.DateTime().timeTime()
1055        start_chunk = DateTime.DateTime().timeTime()
1056        for student in students:
1057            not_all = False
1058            d = self.getFormattedStudentEntry(student)
1059            lines.append(format % d)
1060            total += 1
1061            if total and not total % chunk or total == len(students):
1062                open(export_file,"a").write('\n'.join(lines) +'\n')
1063                anz = len(lines)
1064                logger.info("wrote %(anz)d  total written %(total)d" % vars())
1065                end_chunk = DateTime.DateTime().timeTime()
1066                duration = end_chunk-start_chunk
1067                per_record = duration/anz
1068                till_now = end_chunk - start
1069                avarage_per_record = till_now/total
1070                estimated_end = DateTime.DateTime(start + avarage_per_record * nr2export)
1071                estimated_end = estimated_end.strftime("%H:%M:%S")
1072                logger.info('%(duration)4.1f, %(per_record)4.3f,end %(estimated_end)s' % vars())
1073                start_chunk = DateTime.DateTime().timeTime()
1074                lines = []
1075        end = DateTime.DateTime().timeTime()
1076        logger.info('total time %6.2f m' % ((end-start)/60))
1077        filename, extension = os.path.splitext(export_file)
1078        from subprocess import call
1079        msg = "wrote %(total)d records to %(export_file)s" % vars()
1080        try:
1081            retcode = call('gzip %s' % (export_file),shell=True)
1082            if retcode == 0:
1083                msg = "wrote %(total)d records to %(export_file)s.gz" % vars()
1084        except OSError, e:
1085            retcode = -99
1086            logger.info("zip failed with %s" % e)
1087        logger.info(msg)
1088        args = {'portal_status_message': msg}
1089        #url = self.REQUEST.get('URL1') + '?' + urlencode(args)
1090        url = self.REQUEST.get('URL2')
1091        return self.REQUEST.RESPONSE.redirect(url)
1092    ###)
1093
1094
1095    security.declareProtected(ModifyPortalContent,"importResults")###(
1096    def importResults(self):
1097        """load Returning Students Results from CSV"""
1098        import transaction
1099        import random
1100        #from pdb import set_trace
1101        wftool = self.portal_workflow
1102        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1103        #students_folder = self.portal_catalog({'meta_type': 'StudentsFolder'})[-1].getObject()
1104        students_folder = self.portal_url.getPortalObject().campus.students
1105        tr_count = 1
1106        total = 0
1107        #name = 'pume_results'
1108        name = 'Results'
1109        table = self.results_import
1110        no_import = []
1111        imported = []
1112        logger = logging.getLogger('Students.StudentsFolder.importResults')
1113        try:
1114            results = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
1115        except:
1116            logger.error('Error reading %s.csv' % name)
1117            return
1118        l = self.portal_catalog({'meta_type': "Course"})
1119        courses = [f.getId for f in l]
1120        start = True
1121        res = table()
1122        regs = []
1123        if len(res) > 0:
1124            regs = [s.key for s in res]
1125        no_course = []
1126        no_course_list = []
1127        course_count = 0
1128        for result in results:
1129            if start:
1130                start = False
1131                logger.info('Start loading from %s.csv' % name)
1132                s = ','.join(['"%s"' % fn for fn in result.keys()])
1133                imported.append(s)
1134                no_import.append('%s,"Error"' % s)
1135                format = ','.join(['"%%(%s)s"' % fn for fn in result.keys()])
1136                format_error = format + ',"%(Error)s"'
1137                no_certificate = "no certificate %s" % format
1138            course_id = result.get('CosCode')
1139            if not course_id:
1140                course_id = 'N/A'
1141                result['CosCode'] = course_id
1142            matric_no = result.get('matric_no').upper()
1143            result['matric_no'] = matric_no
1144            key = matric_no+course_id
1145            if matric_no == '':
1146                result['Error'] = "Empty matric_no"
1147                no_import.append( format_error % result)
1148                continue
1149            if key in regs or self.results_import(key = key):
1150                result['Error'] = "Duplicate"
1151                no_import.append( format_error % result)
1152                continue
1153            if course_id not in courses:
1154                if course_id not in no_course:
1155                    course_count +=1
1156                    no_course.append(course_id)
1157                    no_course_list.append('"%s"' % course_id)
1158                    #result['Error'] = "No Course"
1159                    #logger.info(format_error % result)
1160
1161            result['key'] = key
1162            try:
1163                table.addRecord(**result)
1164            except ValueError:
1165                #import pdb;pdb.set_trace()
1166                result['Error'] = "Duplicate"
1167                no_import.append( format_error % result)
1168                continue
1169
1170            regs.append(key)
1171            imported.append(format % result)
1172            tr_count += 1
1173            if tr_count > 1000:
1174                if len(no_import) > 0:
1175                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1176                             '\n'.join(no_import)+'\n')
1177                    no_import = []
1178                open("%s/import/%simported%s.csv" % (i_home,name,current),"a").write(
1179                                            '\n'.join(imported) + '\n')
1180                imported = []
1181                if no_course_list:
1182                    open("%s/import/%sno_courses%s.csv" % (i_home,name,current),"a").write(
1183                                            '\n'.join(no_course_list) + '\n')
1184                    no_course_list = []
1185                em = '%d transactions commited total %s\n courses not found %s' % (tr_count,total,course_count)
1186                transaction.commit()
1187                logger.info(em)
1188                regs = []
1189                total += tr_count
1190                tr_count = 0
1191        open("%s/import/%simported%s.csv" % (i_home,name,current),"a").write(
1192                                            '\n'.join(imported))
1193        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1194                                                '\n'.join(no_import))
1195        if no_course_list:
1196            open("%s/import/%sno_courses%s.csv" % (i_home,name,current),"a").write(
1197                                    '\n'.join(no_course_list))
1198        em = '%d transactions commited total %s\n courses not found %s' % (tr_count,total,course_count)
1199        logger.info(em)
1200        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
1201    ###)
1202
1203    security.declareProtected(ModifyPortalContent,"updateStudyCourse")###(
1204    def updateStudyCourse(self):
1205        """update StudyCourse from CSV values"""
1206        import transaction
1207        import random
1208        from pdb import set_trace
1209        wftool = self.portal_workflow
1210        #students_folder = self.portal_catalog({'meta_type': 'StudentsFolder'})[-1].getObject()
1211        students_folder = self.portal_url.getPortalObject().campus.students
1212        csv_d = {'jamb_reg_no': "RegNumber",
1213                 'jamb_lastname': "Name",
1214                 'session': "Session",
1215                 'pume_tot_score': "PUME SCORE",
1216                 'jamb_score': "JambScore",
1217                 'jamb_sex': "Sex",
1218                 'jamb_state': "State",
1219##                 'jamb_first_cos': "AdminCourse",
1220                 'faculty': "AdminFaculty",
1221                 'course_code': "AdmitCoscode",
1222                 'stud_status':"AdmitStatus",
1223                 'department': "AdmitDept",
1224                 'jamb_lga': "LGA",
1225                 'app_email': "email",
1226                 'app_mobile': "PhoneNumbers",
1227                 }
1228        csv_fields = [f[1] for f in csv_d.items()]
1229        tr_count = 0
1230        total = 0
1231        #name = 'pume_results'
1232        name = 'StudyCourseChange'
1233        no_import = []
1234        s = ','.join(['"%s"' % fn for fn in csv_fields])
1235        no_import.append('"Error",%s' % s)
1236        format = '"%(Error)s",' + ','.join(['"%%(%s)s"' % fn for fn in csv_fields])
1237        no_certificate = "no certificate %s" % format
1238        open("%s/import/%s_not_imported.csv" % (i_home,name),"w").write(
1239                    '\n'.join(no_import))
1240        logger = logging.getLogger('Students.StudentsFolder.updateStudyCourse')
1241        logger.info('Start loading from %s.csv' % name)
1242        l = self.portal_catalog({'meta_type': "Certificate"})
1243        try:
1244            result = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
1245        except:
1246            logger.error('Error reading %s.csv' % name)
1247            return
1248        for jamb in result:
1249            jamb['Error'] = "Processing "
1250            logger.info(format % jamb)
1251            jamb_reg_no = jamb.get(csv_d['jamb_reg_no'])
1252            res = self.portal_catalog({'portal_type': "StudentApplication",
1253                                     'SearchableText': jamb_reg_no })
1254            if not res:
1255                em = 'Student with jamb_reg_no %s does not exists\n' % jamb_reg_no
1256                logger.info(em)
1257                jamb['Error'] = "Student does not exist"
1258                no_import.append(format % jamb)
1259                continue
1260            sid = res[0].getPath().split('/')[-2]
1261            cert_id = makeCertificateCode(jamb.get(csv_d['course_code']))
1262            res = self.portal_catalog(portal_type = "Certificate", id = cert_id)
1263            if not res:
1264                em = 'No Certificate with ID %s \n' % cert_id
1265                logger.info(em)
1266                jamb['Error'] = "No Certificate %s" % cert_id
1267                no_import.append( format % jamb)
1268                continue
1269            cert_brain = res[0]
1270            catalog_entry = {}
1271            student = getattr(self,sid)
1272            #
1273            # Study Course
1274            #
1275            study_course = student.study_course
1276            dsc = {}
1277            cert_pl = cert_brain.getPath().split('/')
1278            catalog_entry['id'] = sid
1279            catalog_entry['faculty'] = cert_pl[-4]
1280            catalog_entry['department'] = cert_pl[-3]
1281            catalog_entry['course'] = cert_id
1282            dsc['study_course'] = cert_id
1283            study_course.getContent().edit(mapping=dsc)
1284            self.students_catalog.modifyRecord(**catalog_entry)
1285            if tr_count > 10:
1286                if len(no_import) > 1:
1287                    open("%s/import/%s_not_imported.csv" % (i_home,name),"w+").write(
1288                             '\n'.join(no_import))
1289                    no_import = []
1290                em = '%d transactions commited\n' % tr_count
1291                transaction.commit()
1292                logger.info(em)
1293                total += tr_count
1294                tr_count = 0
1295            tr_count += 1
1296        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
1297    ###)
1298
1299    security.declareProtected(View,"fixOwnership") ###(
1300    def fixOwnership(self):
1301        """fix Ownership"""
1302        for s in self.portal_catalog(meta_type = 'Student'):
1303            student = s.getObject()
1304            sid = s.getId
1305            import pdb;pdb.set_trace()
1306            student.application.manage_setLocalRoles(sid, ['Owner',])
1307            student.personal.manage_setLocalRoles(sid, ['Owner',])
1308    ###)
1309
1310    security.declareProtected(View,"Title") ###(
1311    def Title(self):
1312        """compose title"""
1313        return "Student Section"
1314    ###)
1315
1316    def generateStudentId(self,letter,students = None): ###(
1317        import random
1318        r = random
1319        if students is None:
1320            students = self.portal_url.getPortalObject().campus.students
1321        if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
1322            letter= r.choice('ABCDEFGHKLMNPQRSTUVWXY')
1323        sid = "%c%d" % (letter,r.randint(99999,1000000))
1324        while hasattr(students, sid):
1325            sid = "%c%d" % (letter,r.randint(99999,1000000))
1326        return sid
1327        #return "%c%d" % (r.choice('ABCDEFGHKLMNPQRSTUVWXY'),r.randint(99999,1000000))
1328    ###)
1329
1330InitializeClass(StudentsFolder)
1331
1332def addStudentsFolder(container, id, REQUEST=None, **kw): ###(
1333    """Add a Student."""
1334    ob = StudentsFolder(id, **kw)
1335    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1336    ###)
1337
1338###)
1339
1340class Student(CPSDocument): ###(
1341    """
1342    WAeUP Student container for the various student data
1343    """
1344    meta_type = 'Student'
1345    portal_type = meta_type
1346    security = ClassSecurityInfo()
1347
1348    security.declareProtected(View,"Title")
1349    def Title(self):
1350        """compose title"""
1351        reg_nr = self.getId()[1:]
1352        data = getattr(self,'personal',None)
1353        if data:
1354            content = data.getContent()
1355            return "%s %s %s" % (content.firstname,content.middlename,content.lastname)
1356        data = getattr(self,'application',None)
1357        if data:
1358            content = data.getContent()
1359            return "%s" % (content.jamb_lastname)
1360        return self.title
1361
1362    security.declarePrivate('makeStudentMember') ###(
1363    def makeStudentMember(self,sid,password='uNsEt'):
1364        """make the student a member"""
1365        membership = self.portal_membership
1366        membership.addMember(sid,
1367                             password ,
1368                             roles=('Member',
1369                                     'Student',
1370                                     ),
1371                             domains='',
1372                             properties = {'memberareaCreationFlag': False,
1373                                           'homeless': True},)
1374        member = membership.getMemberById(sid)
1375        self.portal_registration.afterAdd(member, sid, password, None)
1376        self.manage_setLocalRoles(sid, ['Owner',])
1377
1378###)
1379
1380    security.declareProtected(View,'createSubObjects') ###(
1381    def createSubObjects(self):
1382        """make the student a member"""
1383        dp = {'Title': 'Personal Data'}
1384        app_doc = self.application.getContent()
1385        names = app_doc.jamb_lastname.split()
1386        if len(names) == 3:
1387            dp['firstname'] = names[0].capitalize()
1388            dp['middlename'] = names[1].capitalize()
1389            dp['lastname'] = names[2].capitalize()
1390        elif len(names) == 2:
1391            dp['firstname'] = names[0].capitalize()
1392            dp['lastname'] = names[1].capitalize()
1393        else:
1394            dp['lastname'] = app_doc.jamb_lastname
1395        dp['sex'] = app_doc.jamb_sex == 'F'
1396        dp['lga'] = "%s/%s" % (app_doc.jamb_state,app_doc.jamb_lga )
1397        proxy = self.aq_parent
1398        proxy.invokeFactory('StudentPersonal','personal')
1399        per = proxy.personal
1400        per_doc = per.getContent()
1401        per_doc.edit(mapping = dp)
1402        per.manage_setLocalRoles(proxy.getId(), ['Owner',])
1403        #self.portal_workflow.doActionFor(per,'open',dest_container=per)
1404
1405###)
1406
1407InitializeClass(Student)
1408
1409def addStudent(container, id, REQUEST=None, **kw):
1410    """Add a Student."""
1411    ob = Student(id, **kw)
1412    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1413
1414###)
1415
1416class StudentAccommodation(CPSDocument): ###(
1417    """
1418    WAeUP Student container for the various student data
1419    """
1420    meta_type = 'StudentAccommodation'
1421    portal_type = meta_type
1422    security = ClassSecurityInfo()
1423
1424    security.declareProtected(View,"Title")
1425    def Title(self):
1426        """compose title"""
1427        content = self.getContent()
1428        #return "Accommodation Data for %s %s" % (content.firstname,content.lastname)
1429        return "Accommodation Data for Session %s" % content.session
1430
1431
1432InitializeClass(StudentAccommodation)
1433
1434def addStudentAccommodation(container, id, REQUEST=None, **kw):
1435    """Add a Students personal data."""
1436    ob = StudentAccommodation(id, **kw)
1437    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1438
1439###)
1440
1441class StudentPersonal(CPSDocument): ###(
1442    """
1443    WAeUP Student container for the various student data
1444    """
1445    meta_type = 'StudentPersonal'
1446    portal_type = meta_type
1447    security = ClassSecurityInfo()
1448
1449    security.declareProtected(View,"Title")
1450    def Title(self):
1451        """compose title"""
1452        content = self.getContent()
1453        #return "Personal Data for %s %s" % (content.firstname,content.lastname)
1454        return "Personal Data"
1455
1456
1457InitializeClass(StudentPersonal)
1458
1459def addStudentPersonal(container, id, REQUEST=None, **kw):
1460    """Add a Students personal data."""
1461    ob = StudentPersonal(id, **kw)
1462    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1463
1464###)
1465
1466class StudentClearance(CPSDocument): ###(
1467    """
1468    WAeUP Student container for the various student data
1469    """
1470    meta_type = 'StudentClearance'
1471    portal_type = meta_type
1472    security = ClassSecurityInfo()
1473
1474    security.declareProtected(View,"Title")
1475    def Title(self):
1476        """compose title"""
1477        content = self.getContent()
1478        #return "Clearance/Eligibility Record for %s %s" % (content.firstname,content.lastname)
1479        return "Clearance/Eligibility Record"
1480
1481
1482InitializeClass(StudentClearance)
1483
1484def addStudentClearance(container, id, REQUEST=None, **kw):
1485    """Add a Students personal data."""
1486    ob = StudentClearance(id, **kw)
1487    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1488
1489###)
1490
1491class StudentStudyLevel(CPSDocument): ###(
1492    """
1493    WAeUP Student container for the various student data
1494    """
1495    meta_type = 'StudentStudyLevel'
1496    portal_type = meta_type
1497    security = ClassSecurityInfo()
1498
1499    security.declareProtected(View,"Title")
1500    def Title(self):
1501        """compose title"""
1502        return "Level %s" % self.aq_parent.getId()
1503
1504    def create_course_results(self,cert_id,current_level): ###(
1505        "create all courses in a level"
1506        aq_portal = self.portal_catalog.evalAdvancedQuery
1507        res = self.portal_catalog(portal_type="Certificate", id = cert_id)
1508        l = []
1509        import transaction
1510        if res:
1511            cert = res[0]
1512            path = cert.getPath()
1513            query = Eq("path","%s/%s" % (path,current_level)) &\
1514                    Eq('portal_type','CertificateCourse')
1515            courses = aq_portal(query)
1516            #from pdb import set_trace;set_trace()
1517            self_proxy = self.aq_parent
1518            for c in courses:
1519                d = self.getCourseInfo(c.getId)
1520                cr_id = self_proxy.invokeFactory('StudentCourseResult',c.getId)
1521                course_result = getattr(self_proxy,cr_id)
1522                self.portal_workflow.doActionFor(course_result,'open')
1523                d['core_or_elective'] = getattr(c.getObject().getContent(),'core_or_elective')
1524                course_result.getContent().edit(mapping=d)
1525                #transaction.commit()
1526    ###)
1527
1528InitializeClass(StudentStudyLevel)
1529
1530def addStudentStudyLevel(container, id, REQUEST=None, **kw):
1531    """Add a Students personal data."""
1532    ob = StudentStudyLevel(id, **kw)
1533    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1534
1535###)
1536
1537class StudentStudyCourse(CPSDocument): ###(
1538    """
1539    WAeUP Student container for the various student data
1540    """
1541    meta_type = 'StudentStudyCourse'
1542    portal_type = meta_type
1543    security = ClassSecurityInfo()
1544
1545    security.declareProtected(View,"Title")
1546    def Title(self):
1547        """compose title"""
1548        content = self.getContent()
1549        return "Study Course"
1550
1551
1552InitializeClass(StudentStudyCourse)
1553
1554def addStudentStudyCourse(container, id, REQUEST=None, **kw):
1555    """Add a Students personal data."""
1556    ob = StudentStudyCourse(id, **kw)
1557    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1558
1559###)
1560
1561class StudentApplication(CPSDocument): ###(
1562    """
1563    WAeUP Student container for the various student data
1564    """
1565    meta_type = 'StudentApplication'
1566    portal_type = meta_type
1567    security = ClassSecurityInfo()
1568
1569    security.declareProtected(View,"Title")
1570    def Title(self):
1571        """compose title"""
1572        return "Application Data"
1573
1574
1575InitializeClass(StudentApplication)
1576
1577def addStudentApplication(container, id, REQUEST=None, **kw):
1578    """Add a Students eligibility data."""
1579    ob = StudentApplication(id, **kw)
1580    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1581###)
1582
1583class StudentPume(CPSDocument): ###(
1584    """
1585    WAeUP Student container for the various student data
1586    """
1587    meta_type = 'StudentPume'
1588    portal_type = meta_type
1589    security = ClassSecurityInfo()
1590
1591    security.declareProtected(View,"Title")
1592    def Title(self):
1593        """compose title"""
1594        return "PUME Results"
1595
1596
1597InitializeClass(StudentPume)
1598
1599def addStudentPume(container, id, REQUEST=None, **kw):
1600    """Add a Students PUME data."""
1601    ob = StudentPume(id, **kw)
1602    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1603###)
1604
1605##class StudentSemester(CPSDocument): ###(
1606##    """
1607##    WAeUP StudentSemester containing the courses and students
1608##    """
1609##    meta_type = 'StudentSemester'
1610##    portal_type = meta_type
1611##    security = ClassSecurityInfo()
1612##
1613##InitializeClass(StudentSemester)
1614##
1615##def addStudentSemester(container, id, REQUEST=None, **kw):
1616##    """Add a StudentSemester."""
1617##    ob = StudentSemester(id, **kw)
1618##    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1619##
1620#####)
1621
1622##class Semester(CPSDocument): ###(
1623##    """
1624##    WAeUP Semester containing the courses and students
1625##    """
1626##    meta_type = 'Semester'
1627##    portal_type = meta_type
1628##    security = ClassSecurityInfo()
1629##
1630##InitializeClass(Semester)
1631##
1632##def addSemester(container, id, REQUEST=None, **kw):
1633##    """Add a Semester."""
1634##    ob = Semester(id, **kw)
1635##    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1636##
1637#####)
1638
1639class StudentCourseResult(CPSDocument): ###(
1640    """
1641    WAeUP StudentCourseResult
1642    """
1643    meta_type = 'StudentCourseResult'
1644    portal_type = meta_type
1645    security = ClassSecurityInfo()
1646
1647    def getCourseEntry(self,cid):
1648        res = self.portal_catalog({'meta_type': "Course",
1649                                           'id': cid})
1650        if res:
1651            return res[-1]
1652        else:
1653            return None
1654
1655    security.declareProtected(View,"Title")
1656    def Title(self):
1657        """compose title"""
1658        cid = self.aq_parent.getId()
1659        ce = self.getCourseEntry(cid)
1660        if ce:
1661            return "%s" % ce.Title
1662        return "No course with id %s" % cid
1663
1664InitializeClass(StudentCourseResult)
1665
1666def addStudentCourseResult(container, id, REQUEST=None, **kw):
1667    """Add a StudentCourseResult."""
1668    ob = StudentCourseResult(id, **kw)
1669    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1670###)
1671
1672# Backward Compatibility StudyLevel
1673
1674from Products.WAeUP_SRP.Academics import StudyLevel
1675
1676from Products.WAeUP_SRP.Academics import addStudyLevel
1677
Note: See TracBrowser for help on using the repository browser.