source: WAeUP_SRP/trunk/Students.py @ 2062

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

logging message corrected

  • Property svn:keywords set to Id
File size: 67.2 KB
Line 
1#-*- mode: python; mode: fold -*-
2# $Id: Students.py 2038 2007-07-20 04:49:17Z 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        total = len(results)
1119        l = self.portal_catalog({'meta_type': "Course"})
1120        courses = [f.getId for f in l]
1121        start = True
1122        res = table()
1123        regs = []
1124        if len(res) > 0:
1125            regs = [s.key for s in res]
1126        no_course = []
1127        no_course_list = []
1128        course_count = 0
1129        for result in results:
1130            if start:
1131                start = False
1132                logger.info('Start loading from %s.csv' % name)
1133                s = ','.join(['"%s"' % fn for fn in result.keys()])
1134                imported.append(s)
1135                no_import.append('%s,"Error"' % s)
1136                format = ','.join(['"%%(%s)s"' % fn for fn in result.keys()])
1137                format_error = format + ',"%(Error)s"'
1138                no_certificate = "no certificate %s" % format
1139            course_id = result.get('CosCode')
1140            if not course_id:
1141                course_id = 'N/A'
1142                result['CosCode'] = course_id
1143            matric_no = result.get('matric_no').upper()
1144            result['matric_no'] = matric_no
1145            key = matric_no+course_id
1146            if matric_no == '':
1147                result['Error'] = "Empty matric_no"
1148                no_import.append( format_error % result)
1149                continue
1150            if key in regs or self.results_import(key = key):
1151                result['Error'] = "Duplicate"
1152                no_import.append( format_error % result)
1153                continue
1154            if course_id not in courses:
1155                if course_id not in no_course:
1156                    course_count +=1
1157                    no_course.append(course_id)
1158                    no_course_list.append('"%s"' % course_id)
1159                    #result['Error'] = "No Course"
1160                    #logger.info(format_error % result)
1161
1162            result['key'] = key
1163            try:
1164                table.addRecord(**result)
1165            except ValueError:
1166                #import pdb;pdb.set_trace()
1167                result['Error'] = "Duplicate"
1168                no_import.append( format_error % result)
1169                continue
1170
1171            regs.append(key)
1172            imported.append(format % result)
1173            tr_count += 1
1174            if tr_count > 1000:
1175                if len(no_import) > 0:
1176                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1177                             '\n'.join(no_import)+'\n')
1178                    no_import = []
1179                open("%s/import/%simported%s.csv" % (i_home,name,current),"a").write(
1180                                            '\n'.join(imported) + '\n')
1181                imported = []
1182                if no_course_list:
1183                    open("%s/import/%sno_courses%s.csv" % (i_home,name,current),"a").write(
1184                                            '\n'.join(no_course_list) + '\n')
1185                    no_course_list = []
1186                em = '%d transactions comitted, %s courses not found ' % (tr_count,course_count)
1187                transaction.commit()
1188                logger.info(em)
1189                regs = []
1190                total += tr_count
1191                #tr_count = 0
1192        open("%s/import/%simported%s.csv" % (i_home,name,current),"a").write(
1193                                            '\n'.join(imported))
1194        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1195                                                '\n'.join(no_import))
1196        if no_course_list:
1197            open("%s/import/%sno_courses%s.csv" % (i_home,name,current),"a").write(
1198                                    '\n'.join(no_course_list))
1199        em = '%d transactions of %s committed, %s courses not found ' % (tr_count,total,course_count)
1200        logger.info(em)
1201        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
1202    ###)
1203
1204    security.declareProtected(ModifyPortalContent,"updateStudyCourse")###(
1205    def updateStudyCourse(self):
1206        """update StudyCourse from CSV values"""
1207        import transaction
1208        import random
1209        from pdb import set_trace
1210        wftool = self.portal_workflow
1211        #students_folder = self.portal_catalog({'meta_type': 'StudentsFolder'})[-1].getObject()
1212        students_folder = self.portal_url.getPortalObject().campus.students
1213        csv_d = {'jamb_reg_no': "RegNumber",
1214                 'jamb_lastname': "Name",
1215                 'session': "Session",
1216                 'pume_tot_score': "PUME SCORE",
1217                 'jamb_score': "JambScore",
1218                 'jamb_sex': "Sex",
1219                 'jamb_state': "State",
1220##                 'jamb_first_cos': "AdminCourse",
1221                 'faculty': "AdminFaculty",
1222                 'course_code': "AdmitCoscode",
1223                 'stud_status':"AdmitStatus",
1224                 'department': "AdmitDept",
1225                 'jamb_lga': "LGA",
1226                 'app_email': "email",
1227                 'app_mobile': "PhoneNumbers",
1228                 }
1229        csv_fields = [f[1] for f in csv_d.items()]
1230        tr_count = 0
1231        total = 0
1232        #name = 'pume_results'
1233        name = 'StudyCourseChange'
1234        no_import = []
1235        s = ','.join(['"%s"' % fn for fn in csv_fields])
1236        no_import.append('"Error",%s' % s)
1237        format = '"%(Error)s",' + ','.join(['"%%(%s)s"' % fn for fn in csv_fields])
1238        no_certificate = "no certificate %s" % format
1239        open("%s/import/%s_not_imported.csv" % (i_home,name),"w").write(
1240                    '\n'.join(no_import))
1241        logger = logging.getLogger('Students.StudentsFolder.updateStudyCourse')
1242        logger.info('Start loading from %s.csv' % name)
1243        l = self.portal_catalog({'meta_type': "Certificate"})
1244        try:
1245            result = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
1246        except:
1247            logger.error('Error reading %s.csv' % name)
1248            return
1249        for jamb in result:
1250            jamb['Error'] = "Processing "
1251            logger.info(format % jamb)
1252            jamb_reg_no = jamb.get(csv_d['jamb_reg_no'])
1253            res = self.portal_catalog({'portal_type': "StudentApplication",
1254                                     'SearchableText': jamb_reg_no })
1255            if not res:
1256                em = 'Student with jamb_reg_no %s does not exists\n' % jamb_reg_no
1257                logger.info(em)
1258                jamb['Error'] = "Student does not exist"
1259                no_import.append(format % jamb)
1260                continue
1261            sid = res[0].getPath().split('/')[-2]
1262            cert_id = makeCertificateCode(jamb.get(csv_d['course_code']))
1263            res = self.portal_catalog(portal_type = "Certificate", id = cert_id)
1264            if not res:
1265                em = 'No Certificate with ID %s \n' % cert_id
1266                logger.info(em)
1267                jamb['Error'] = "No Certificate %s" % cert_id
1268                no_import.append( format % jamb)
1269                continue
1270            cert_brain = res[0]
1271            catalog_entry = {}
1272            student = getattr(self,sid)
1273            #
1274            # Study Course
1275            #
1276            study_course = student.study_course
1277            dsc = {}
1278            cert_pl = cert_brain.getPath().split('/')
1279            catalog_entry['id'] = sid
1280            catalog_entry['faculty'] = cert_pl[-4]
1281            catalog_entry['department'] = cert_pl[-3]
1282            catalog_entry['course'] = cert_id
1283            dsc['study_course'] = cert_id
1284            study_course.getContent().edit(mapping=dsc)
1285            self.students_catalog.modifyRecord(**catalog_entry)
1286            if tr_count > 10:
1287                if len(no_import) > 1:
1288                    open("%s/import/%s_not_imported.csv" % (i_home,name),"w+").write(
1289                             '\n'.join(no_import))
1290                    no_import = []
1291                em = '%d transactions commited\n' % tr_count
1292                transaction.commit()
1293                logger.info(em)
1294                total += tr_count
1295                tr_count = 0
1296            tr_count += 1
1297        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
1298    ###)
1299
1300    security.declareProtected(View,"fixOwnership") ###(
1301    def fixOwnership(self):
1302        """fix Ownership"""
1303        for s in self.portal_catalog(meta_type = 'Student'):
1304            student = s.getObject()
1305            sid = s.getId
1306            import pdb;pdb.set_trace()
1307            student.application.manage_setLocalRoles(sid, ['Owner',])
1308            student.personal.manage_setLocalRoles(sid, ['Owner',])
1309    ###)
1310
1311    security.declareProtected(View,"Title") ###(
1312    def Title(self):
1313        """compose title"""
1314        return "Student Section"
1315    ###)
1316
1317    def generateStudentId(self,letter,students = None): ###(
1318        import random
1319        r = random
1320        if students is None:
1321            students = self.portal_url.getPortalObject().campus.students
1322        if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
1323            letter= r.choice('ABCDEFGHKLMNPQRSTUVWXY')
1324        sid = "%c%d" % (letter,r.randint(99999,1000000))
1325        while hasattr(students, sid):
1326            sid = "%c%d" % (letter,r.randint(99999,1000000))
1327        return sid
1328        #return "%c%d" % (r.choice('ABCDEFGHKLMNPQRSTUVWXY'),r.randint(99999,1000000))
1329    ###)
1330
1331InitializeClass(StudentsFolder)
1332
1333def addStudentsFolder(container, id, REQUEST=None, **kw): ###(
1334    """Add a Student."""
1335    ob = StudentsFolder(id, **kw)
1336    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1337    ###)
1338
1339###)
1340
1341class Student(CPSDocument): ###(
1342    """
1343    WAeUP Student container for the various student data
1344    """
1345    meta_type = 'Student'
1346    portal_type = meta_type
1347    security = ClassSecurityInfo()
1348
1349    security.declareProtected(View,"Title")
1350    def Title(self):
1351        """compose title"""
1352        reg_nr = self.getId()[1:]
1353        data = getattr(self,'personal',None)
1354        if data:
1355            content = data.getContent()
1356            return "%s %s %s" % (content.firstname,content.middlename,content.lastname)
1357        data = getattr(self,'application',None)
1358        if data:
1359            content = data.getContent()
1360            return "%s" % (content.jamb_lastname)
1361        return self.title
1362
1363    security.declarePrivate('makeStudentMember') ###(
1364    def makeStudentMember(self,sid,password='uNsEt'):
1365        """make the student a member"""
1366        membership = self.portal_membership
1367        membership.addMember(sid,
1368                             password ,
1369                             roles=('Member',
1370                                     'Student',
1371                                     ),
1372                             domains='',
1373                             properties = {'memberareaCreationFlag': False,
1374                                           'homeless': True},)
1375        member = membership.getMemberById(sid)
1376        self.portal_registration.afterAdd(member, sid, password, None)
1377        self.manage_setLocalRoles(sid, ['Owner',])
1378
1379###)
1380
1381    security.declareProtected(View,'createSubObjects') ###(
1382    def createSubObjects(self):
1383        """make the student a member"""
1384        dp = {'Title': 'Personal Data'}
1385        app_doc = self.application.getContent()
1386        names = app_doc.jamb_lastname.split()
1387        if len(names) == 3:
1388            dp['firstname'] = names[0].capitalize()
1389            dp['middlename'] = names[1].capitalize()
1390            dp['lastname'] = names[2].capitalize()
1391        elif len(names) == 2:
1392            dp['firstname'] = names[0].capitalize()
1393            dp['lastname'] = names[1].capitalize()
1394        else:
1395            dp['lastname'] = app_doc.jamb_lastname
1396        dp['sex'] = app_doc.jamb_sex == 'F'
1397        dp['lga'] = "%s/%s" % (app_doc.jamb_state,app_doc.jamb_lga )
1398        proxy = self.aq_parent
1399        proxy.invokeFactory('StudentPersonal','personal')
1400        per = proxy.personal
1401        per_doc = per.getContent()
1402        per_doc.edit(mapping = dp)
1403        per.manage_setLocalRoles(proxy.getId(), ['Owner',])
1404        #self.portal_workflow.doActionFor(per,'open',dest_container=per)
1405
1406###)
1407
1408InitializeClass(Student)
1409
1410def addStudent(container, id, REQUEST=None, **kw):
1411    """Add a Student."""
1412    ob = Student(id, **kw)
1413    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1414
1415###)
1416
1417class StudentAccommodation(CPSDocument): ###(
1418    """
1419    WAeUP Student container for the various student data
1420    """
1421    meta_type = 'StudentAccommodation'
1422    portal_type = meta_type
1423    security = ClassSecurityInfo()
1424
1425    security.declareProtected(View,"Title")
1426    def Title(self):
1427        """compose title"""
1428        content = self.getContent()
1429        #return "Accommodation Data for %s %s" % (content.firstname,content.lastname)
1430        return "Accommodation Data for Session %s" % content.session
1431
1432
1433InitializeClass(StudentAccommodation)
1434
1435def addStudentAccommodation(container, id, REQUEST=None, **kw):
1436    """Add a Students personal data."""
1437    ob = StudentAccommodation(id, **kw)
1438    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1439
1440###)
1441
1442class StudentPersonal(CPSDocument): ###(
1443    """
1444    WAeUP Student container for the various student data
1445    """
1446    meta_type = 'StudentPersonal'
1447    portal_type = meta_type
1448    security = ClassSecurityInfo()
1449
1450    security.declareProtected(View,"Title")
1451    def Title(self):
1452        """compose title"""
1453        content = self.getContent()
1454        #return "Personal Data for %s %s" % (content.firstname,content.lastname)
1455        return "Personal Data"
1456
1457
1458InitializeClass(StudentPersonal)
1459
1460def addStudentPersonal(container, id, REQUEST=None, **kw):
1461    """Add a Students personal data."""
1462    ob = StudentPersonal(id, **kw)
1463    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1464
1465###)
1466
1467class StudentClearance(CPSDocument): ###(
1468    """
1469    WAeUP Student container for the various student data
1470    """
1471    meta_type = 'StudentClearance'
1472    portal_type = meta_type
1473    security = ClassSecurityInfo()
1474
1475    security.declareProtected(View,"Title")
1476    def Title(self):
1477        """compose title"""
1478        content = self.getContent()
1479        #return "Clearance/Eligibility Record for %s %s" % (content.firstname,content.lastname)
1480        return "Clearance/Eligibility Record"
1481
1482
1483InitializeClass(StudentClearance)
1484
1485def addStudentClearance(container, id, REQUEST=None, **kw):
1486    """Add a Students personal data."""
1487    ob = StudentClearance(id, **kw)
1488    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1489
1490###)
1491
1492class StudentStudyLevel(CPSDocument): ###(
1493    """
1494    WAeUP Student container for the various student data
1495    """
1496    meta_type = 'StudentStudyLevel'
1497    portal_type = meta_type
1498    security = ClassSecurityInfo()
1499
1500    security.declareProtected(View,"Title")
1501    def Title(self):
1502        """compose title"""
1503        return "Level %s" % self.aq_parent.getId()
1504
1505    def create_course_results(self,cert_id,current_level): ###(
1506        "create all courses in a level"
1507        aq_portal = self.portal_catalog.evalAdvancedQuery
1508        res = self.portal_catalog(portal_type="Certificate", id = cert_id)
1509        l = []
1510        import transaction
1511        if res:
1512            cert = res[0]
1513            path = cert.getPath()
1514            query = Eq("path","%s/%s" % (path,current_level)) &\
1515                    Eq('portal_type','CertificateCourse')
1516            courses = aq_portal(query)
1517            #from pdb import set_trace;set_trace()
1518            self_proxy = self.aq_parent
1519            for c in courses:
1520                d = self.getCourseInfo(c.getId)
1521                cr_id = self_proxy.invokeFactory('StudentCourseResult',c.getId)
1522                course_result = getattr(self_proxy,cr_id)
1523                self.portal_workflow.doActionFor(course_result,'open')
1524                d['core_or_elective'] = getattr(c.getObject().getContent(),'core_or_elective')
1525                course_result.getContent().edit(mapping=d)
1526                #transaction.commit()
1527    ###)
1528
1529InitializeClass(StudentStudyLevel)
1530
1531def addStudentStudyLevel(container, id, REQUEST=None, **kw):
1532    """Add a Students personal data."""
1533    ob = StudentStudyLevel(id, **kw)
1534    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1535
1536###)
1537
1538class StudentStudyCourse(CPSDocument): ###(
1539    """
1540    WAeUP Student container for the various student data
1541    """
1542    meta_type = 'StudentStudyCourse'
1543    portal_type = meta_type
1544    security = ClassSecurityInfo()
1545
1546    security.declareProtected(View,"Title")
1547    def Title(self):
1548        """compose title"""
1549        content = self.getContent()
1550        return "Study Course"
1551
1552
1553InitializeClass(StudentStudyCourse)
1554
1555def addStudentStudyCourse(container, id, REQUEST=None, **kw):
1556    """Add a Students personal data."""
1557    ob = StudentStudyCourse(id, **kw)
1558    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1559
1560###)
1561
1562class StudentApplication(CPSDocument): ###(
1563    """
1564    WAeUP Student container for the various student data
1565    """
1566    meta_type = 'StudentApplication'
1567    portal_type = meta_type
1568    security = ClassSecurityInfo()
1569
1570    security.declareProtected(View,"Title")
1571    def Title(self):
1572        """compose title"""
1573        return "Application Data"
1574
1575
1576InitializeClass(StudentApplication)
1577
1578def addStudentApplication(container, id, REQUEST=None, **kw):
1579    """Add a Students eligibility data."""
1580    ob = StudentApplication(id, **kw)
1581    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1582###)
1583
1584class StudentPume(CPSDocument): ###(
1585    """
1586    WAeUP Student container for the various student data
1587    """
1588    meta_type = 'StudentPume'
1589    portal_type = meta_type
1590    security = ClassSecurityInfo()
1591
1592    security.declareProtected(View,"Title")
1593    def Title(self):
1594        """compose title"""
1595        return "PUME Results"
1596
1597
1598InitializeClass(StudentPume)
1599
1600def addStudentPume(container, id, REQUEST=None, **kw):
1601    """Add a Students PUME data."""
1602    ob = StudentPume(id, **kw)
1603    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1604###)
1605
1606##class StudentSemester(CPSDocument): ###(
1607##    """
1608##    WAeUP StudentSemester containing the courses and students
1609##    """
1610##    meta_type = 'StudentSemester'
1611##    portal_type = meta_type
1612##    security = ClassSecurityInfo()
1613##
1614##InitializeClass(StudentSemester)
1615##
1616##def addStudentSemester(container, id, REQUEST=None, **kw):
1617##    """Add a StudentSemester."""
1618##    ob = StudentSemester(id, **kw)
1619##    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1620##
1621#####)
1622
1623##class Semester(CPSDocument): ###(
1624##    """
1625##    WAeUP Semester containing the courses and students
1626##    """
1627##    meta_type = 'Semester'
1628##    portal_type = meta_type
1629##    security = ClassSecurityInfo()
1630##
1631##InitializeClass(Semester)
1632##
1633##def addSemester(container, id, REQUEST=None, **kw):
1634##    """Add a Semester."""
1635##    ob = Semester(id, **kw)
1636##    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1637##
1638#####)
1639
1640class StudentCourseResult(CPSDocument): ###(
1641    """
1642    WAeUP StudentCourseResult
1643    """
1644    meta_type = 'StudentCourseResult'
1645    portal_type = meta_type
1646    security = ClassSecurityInfo()
1647
1648    def getCourseEntry(self,cid):
1649        res = self.portal_catalog({'meta_type': "Course",
1650                                           'id': cid})
1651        if res:
1652            return res[-1]
1653        else:
1654            return None
1655
1656    security.declareProtected(View,"Title")
1657    def Title(self):
1658        """compose title"""
1659        cid = self.aq_parent.getId()
1660        ce = self.getCourseEntry(cid)
1661        if ce:
1662            return "%s" % ce.Title
1663        return "No course with id %s" % cid
1664
1665InitializeClass(StudentCourseResult)
1666
1667def addStudentCourseResult(container, id, REQUEST=None, **kw):
1668    """Add a StudentCourseResult."""
1669    ob = StudentCourseResult(id, **kw)
1670    return CPSBase_adder(container, ob, REQUEST=REQUEST)
1671###)
1672
1673# Backward Compatibility StudyLevel
1674
1675from Products.WAeUP_SRP.Academics import StudyLevel
1676
1677from Products.WAeUP_SRP.Academics import addStudyLevel
1678
Note: See TracBrowser for help on using the repository browser.