source: WAeUP_SRP/trunk/Students.py @ 2127

Last change on this file since 2127 was 2125, checked in by joachim, 17 years ago

fix state lga in formatLGA

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