source: WAeUP_SRP/trunk/Students.py @ 2080

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

dump lga and state separately

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