source: WAeUP_SRP/base/Students.py @ 2238

Last change on this file since 2238 was 2128, checked in by joachim, 17 years ago

dumpStundents now uses csvwriter should do all formatting correct

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