source: WAeUP_SRP/trunk/Students.py @ 2111

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

split lga perfectly

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