source: WAeUP_SRP/base/WAeUPTool.py @ 2393

Last change on this file since 2393 was 2364, checked in by joachim, 17 years ago

new function picturesList in waeup_tool used in clearance_edit

  • Property svn:keywords set to Id
File size: 63.5 KB
Line 
1#-*- mode: python; mode: fold -*-
2# (C) Copyright 2005 The WAeUP group  <http://www.waeup.org>
3# Author: Joachim Schmitz (js@aixtraware.de)
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License version 2 as published
7# by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software
16# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17# 02111-1307, USA.
18#
19# $Id: WAeUPTool.py 2364 2007-10-15 17:03:44Z joachim $
20"""The WAeUP Tool Box.
21"""
22
23from AccessControl import ClassSecurityInfo
24from Acquisition import aq_inner
25from Acquisition import aq_parent
26from Globals import DTMLFile
27from Globals import InitializeClass
28from OFS.SimpleItem import SimpleItem
29from zExceptions import BadRequest
30
31from Products.CMFCore.utils import getToolByName
32from Products.CPSSchemas.DataStructure import DataStructure
33from Products.CPSSchemas.DataModel import DataModel
34from Products.CPSSchemas.StorageAdapter import MappingStorageAdapter
35from Products.CMFCore.ActionProviderBase import ActionProviderBase
36from Products.CMFCore.permissions import View
37from Products.ZCatalog.ZCatalog import ZCatalog
38from Products.CMFCore.permissions import ModifyPortalContent
39from Products.CMFCore.permissions import ManagePortal
40from Products.CMFCore.utils import UniqueObject
41from Products.CMFCore.URLTool import URLTool
42from Products.CMFCore.utils import getToolByName
43from Students import makeCertificateCode
44from Globals import package_home,INSTANCE_HOME
45p_home = package_home(globals())
46i_home = INSTANCE_HOME
47import DateTime,time
48import logging
49import transaction
50import csv,re,os,sys
51from Products.AdvancedQuery import Eq, Between, Le,In
52
53def getObject(object,name):
54    if object.hasObject(name):
55        return getattr(object,name)
56    return None
57
58class WAeUPTool(UniqueObject, SimpleItem, ActionProviderBase):
59    """WAeUP tool"""
60
61    id = 'waeup_tool'
62    meta_type = 'WAeUP Tool'
63    _actions = ()
64    security = ClassSecurityInfo()
65    security.declareObjectProtected(View)
66    manage_options = ( ActionProviderBase.manage_options
67                     + SimpleItem.manage_options
68                     )
69
70    def rwrite(self,s): ###(
71        response = self.REQUEST.RESPONSE
72        response.setHeader('Content-type','text/html; charset=ISO-8859-15')
73        response.write("%s<br />\r\n" % s)
74    ###)
75
76    def sleep(self,secs): ###(
77        "sleep"
78        import time
79        time.sleep(secs)
80        return
81
82###)
83
84    security.declareProtected(ModifyPortalContent,'openLog') ###(
85    def openLog(self,name):
86        """open a log file"""
87        version = 1
88        path = "%s/log/%s_%d.log" % (i_home,name,version)
89        while os.path.exists(path):
90            version += 1
91            path = "%s/log/%s_%d.log" % (i_home,name,version)
92        log = open(path,"w")
93        return log
94    ###)
95
96    security.declareProtected(ModifyPortalContent,'bypassQueueCatalog') ###(
97    def bypassQueueCatalog(self,enable=True):
98        """bypass the QueueCatalog by setting all indexes to process imediate,
99        if enable is True (default) the old settings are restored
100        """
101
102    ###)
103
104    security.declareProtected(ModifyPortalContent,'measureOaT') ###(
105    def measureOaT(self,method="a",probe="1000",nr_pts="1"):
106        """measure Object access Time"""
107        import random
108        if hasattr(self,'portal_catalog_real'):
109            aq_portal = self.portal_catalog_real.evalAdvancedQuery
110        else:
111            aq_portal = self.portal_catalog.evalAdvancedQuery
112        nr_pts = int(nr_pts)
113        probe = int(probe)
114        intervall = probe/10
115        objects = ("application","clearance","personal")
116        portal_types = ("StudentApplication","StudentClearance","StudentPersonal")
117        #i = random.randrange(num_objects)
118        count = 0
119        found = 0
120        not_found = 0
121        t_found = 0
122        t_not_found = 0
123        time_found = time_not_found = 0.0
124        t_time_found = t_time_not_found = 0.0
125        accessed = []
126        t_min = 1000
127        t_max = 0
128        #import pdb;pdb.set_trace()
129        students = self.portal_catalog(portal_type="Student")
130        num_students = len(students)
131        if method == "d":
132            query = Eq('path','/uniben/campus/students') & In('portal_type',portal_types[:nr_pts])
133            res = aq_portal(query)
134            brains = {}
135            for r in res:
136                sid = r.relative_path.split('/')[-2]
137                if brains.has_key(sid):
138                    brains[sid][r.portal_type] = r
139                else:
140                    brains[sid] = {r.portal_type : r}
141            brains_list = brains.keys()
142            num_objects = len(brains_list)
143        else:
144            num_objects = num_students
145        print "="*40
146        print "method: %s probes: %d nr_pts: %d num_objects: %d" % (method,
147                                                                        probe,
148                                                                        nr_pts,
149                                                                        num_objects)
150        print "nr found/not time found/not min/max"
151        elapse = time.time()
152        i_elapse = time.time()
153        c_elapse = time.clock()
154        for c in range(1,probe + 1):
155            i = random.randrange(num_objects)
156            if method in ('a','b','c'):
157                student_brain = students[i]
158            elif method == "d":
159                #import pdb;pdb.set_trace()
160                student_brain = brains[brains_list[i]]
161            if method == "c":
162                query = Eq('path',student_brain.getPath()) & In('portal_type',portal_types[:nr_pts])
163                res = aq_portal(query)
164                this_portal_types = [r.portal_type for r in res]
165            for i in range(nr_pts):
166                oid = objects[i]
167                if method == "a":
168                    try:
169                        student_path = student_brain.getPath()
170                        path = "%s/%s" % (student_path,oid)
171                        doc = self.unrestrictedTraverse(path).getContent()
172                        found += 1
173                        i_time = time.time() - i_elapse
174                        time_found += i_time
175                    except:
176                        not_found += 1
177                        i_time = time.time() - i_elapse
178                        time_not_found += i_time
179                        pass
180                elif method == "b":
181                    try:
182                        student_object = student_brain.getObject()
183                        doc = getattr(student_object,oid).getContent()
184                        found += 1
185                        i_time = time.time() - i_elapse
186                        time_found += i_time
187                    except:
188                        i_time = time.time() - i_elapse
189                        time_not_found += i_time
190                        not_found += 1
191                        pass
192                elif method == "c":
193                    if portal_types[i] in this_portal_types:
194                        found += 1
195                        doc = res[this_portal_types.index(portal_types[i])].getObject().getContent()
196                        i_time = time.time() - i_elapse
197                        time_found += i_time
198                    else:
199                        not_found += 1
200                        i_time = time.time() - i_elapse
201                        time_not_found += i_time
202                elif method == "d":
203                    if student_brain.has_key(portal_types[i]):
204                        found += 1
205                        doc = student_brain[portal_types[i]].getObject().getContent()
206                        i_time = time.time() - i_elapse
207                        time_found += i_time
208                    else:
209                        not_found += 1
210                        i_time = time.time() - i_elapse
211                        time_not_found += i_time
212                i_elapse = time.time()
213            if c and (c % intervall == 0):
214                #i_time = time.time() - i_elapse
215                t_per = 0.0
216                if found:
217                    t_per = time_found/found
218                if t_per > t_max:
219                    t_max = t_per
220                if t_per > 0.0 and t_per < t_min:
221                    t_min = t_per
222                itf = 0.0
223                if found:
224                    itf = time_found/found
225                itnf = 0.0
226                if not_found :
227                    itnf = time_not_found / not_found
228                interval_time = time_found + time_not_found
229                s = "%(c)d: %(found)d/%(not_found)d " % vars()
230                s += "%(interval_time)6.2f %(itf)6.4f/%(itnf)6.4f " % vars()
231                s += "%(t_min)6.4f/%(t_max)6.4f" %  vars()
232                print s
233                t_found += found
234                t_not_found += not_found
235                t_time_found += time_found
236                t_time_not_found += time_not_found
237                time_found = time_not_found = 0.0
238                found = not_found = 0
239        # t_found += found
240        # t_not_found += not_found
241        elapse = time.time() - elapse
242        itf = 0.0
243        if t_found:
244            itf = t_time_found/t_found
245        itnf = 0.0
246        if t_not_found:
247            itnf = t_time_not_found / t_not_found
248        #c_elapse = time.clock() - c_elapse
249        s = "%(probe)d: %(t_found)d/%(t_not_found)d " % vars()
250        s += "%(elapse)6.2f %(itf)6.4f/%(itnf)6.4f " % vars()
251        s += "%(t_min)6.4f/%(t_max)6.4f" %  vars()
252        print "-"*40
253        print s
254        rel_found = float(t_found)/probe
255        rel_not_found = float(t_not_found)/probe
256        estimated_total_time = num_objects*(rel_found*itf + rel_not_found*itnf)
257        print estimated_total_time
258    ###)
259
260    security.declareProtected(ModifyPortalContent,'writeLog') ###(
261    def writeLog(self,logfile,s):
262        """write to the log file"""
263        logfile.write(s)
264
265###)
266
267    def generateStudentId(self,letter): ###(
268        import random
269        r = random
270        ##if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
271        if letter == '?':
272            letter= r.choice('ABCDEFGHKLMNPQRSTUVWXY')
273        sid = "%c%d" % (letter,r.randint(99999,1000000))
274        students = self.portal_url.getPortalObject().campus.students
275##        while hasattr(students, sid):
276##            sid = "%c%d" % (letter,r.randint(99999,1000000))
277        while self.students_catalog(id = sid):
278            sid = "%c%d" % (letter,r.randint(99999,1000000))
279        return sid
280    ###)
281
282    def generatePassword(self,s=None): ###(
283        import random
284        r = random
285        ##if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
286        if s is None:
287            s = 'abcdefghklmnpqrstuvwxy23456789'
288        pw = ''
289        while len(pw) < 6:
290            pw += r.choice(s)
291        return pw
292    ###)
293
294    security.declareProtected(ManagePortal, 'removeDeletedDocIds') ###(
295    def removeDeletedDocIds(self, max=1000):
296        """
297        remove deleted docids from repository commit after max
298        """
299        logger = logging.getLogger('WAeUPTool.removeDeletedDocIds')
300        repository = getToolByName(self, 'portal_repository')
301        pxtool = getToolByName(self, 'portal_proxies')
302        pxtool_infos = pxtool.getRevisionsUsed()
303
304        nb_revs = 0
305        docids_d = {} # all docids
306        unused_docids_d = {} # all docids that are unused
307        ids_unused_revs_docids = [] # ids for revs of unused docids
308        ids_unused_revs = [] # ids for unused revs
309        total = 0
310        idlist = repository.objectIds()
311        for id in idlist:
312            docid, rev = repository._splitId(id)
313            if docid is None:
314                logger.info("invalid doc_id %s" % docid)
315                continue
316            nb_revs += 1
317            docids_d[docid] = None
318            if not pxtool_infos.has_key(docid):
319                unused_docids_d[docid] = None
320                ids_unused_revs_docids.append(id)
321                ids_unused_revs.append(id)
322            elif not pxtool_infos[docid].has_key(rev):
323                ids_unused_revs.append(id)
324            if len(ids_unused_revs) >= max:
325                repository.manage_delObjects(ids_unused_revs)
326                #import pdb;pdb.set_trace()
327                transaction.commit()
328                total += max
329                logger.info('removed %d total %d unused docids ' % (max,total))
330        anz = len(ids_unused_revs)
331        if anz > 0:
332            repository.manage_delObjects(ids_unused_revs)
333            transaction.commit()
334            total += anz
335            logger.info('finished removing %d unused docids ' % (total))
336
337
338###)
339
340    security.declareProtected(View,'getCredential') ###(
341    def getCredential(self,student_id):
342        "return a student password"
343        student_entry = getattr(self.portal_directories.students,student_id,None)
344        if student_entry is None:
345            return None
346        return getattr(student_entry,"password","not set")
347    ###)
348
349    security.declarePublic('checkPassword') ###(
350    def checkPassword(self,student_id,password):
351        "return a student password"
352        student_entry = getattr(self.portal_directories.students,student_id,None)
353        if student_entry is None:
354            return False
355        return getattr(student_entry,"password","not set") == password
356    ###)
357
358    security.declarePublic('editPassword') ###(
359    def editPassword(self,student_id,password):
360        "edit a student password"
361        student_entry = getattr(self.portal_directories.students,student_id,None)
362        if student_entry is None:
363            return
364        setattr(student_entry,'password',password)
365    ###)
366
367    security.declareProtected(View,'doCommit') ###(
368    def doCommit(self,logger=None):
369        "commit some transactions"
370        transaction.commit()
371    ###)
372
373    security.declarePublic('loadStudentFoto') ###(
374    def loadStudentFoto(self,student,filename,folder):
375        "return a student passport picture"
376        app = student.application
377        app_doc = app.getContent()
378        #clear = student.clearance
379        #clear_doc = clear.getContent()
380        #matric_no = clear_doc.matric_no.upper()
381        picture1 ="%s/import/%s/%s.jpg" % (i_home,folder,filename)
382        picture2 ="%s/import/%s/%s.JPG" % (i_home,folder,filename)
383        #import pdb;pdb.set_trace()
384        if os.path.exists(picture1):
385            file = open(picture1)
386        elif os.path.exists(picture2):
387            file = open(picture2)
388        else:
389            return "passport picture not found %s" % picture1
390        reopened = False
391        if self.portal_workflow.getInfoFor(app,'review_state',None) !='opened':
392            self.portal_workflow.doActionFor(app,'open')
393            reopened = True
394        outfile = file.read()
395        app_doc.manage_addFile('passport',
396                               file=outfile,
397                               title="%s.jpg" % filename)
398        if reopened:
399            self.portal_workflow.doActionFor(app,'close')
400        return "successfully loaded passport picture"
401    ###)
402
403    security.declareProtected(ModifyPortalContent,'createOne') ###(
404    def createOne(self,students_folder,student_brain,letter,commit=False):
405        sid = self.waeup_tool.generateStudentId(letter)
406        students_folder.invokeFactory('Student', sid)
407        student = getattr(students_folder,sid)
408        self.portal_workflow.doActionFor(student,'return')
409        student.manage_setLocalRoles(sid, ['Owner',])
410        matric_no = student_brain.matric_no
411        jamb_reg_no = student_brain.Entryregno
412        self.students_catalog.addRecord(id = sid,
413                                           matric_no = matric_no,
414                                           jamb_reg_no = jamb_reg_no,
415                                           sex = student_brain.Sex == "F",
416                                           name = "%s %s %s" % (student_brain.Firstname,
417                                                                student_brain.Middlename,
418                                                                student_brain.Lastname)
419                                        )
420        if commit:
421            transaction.commit()
422        return sid,jamb_reg_no
423    ###)
424
425    security.declareProtected(ModifyPortalContent,'addStudent') ###(
426    def addStudent(self,dict):
427        students_folder = self.portal_url.getPortalObject().campus.students
428        sid = self.waeup_tool.generateStudentId('?')
429        students_folder.invokeFactory('Student', sid)
430        student_obj = getattr(students_folder,sid)
431        f2t = self.student_field2types
432        #from pdb import set_trace; set_trace()
433        d = {}
434        #d['jamb_sex']  = 'M'
435        #if dict.get('sex'):
436        #    d['jamb_sex']  = 'F'
437
438        entry_session = dict.get('entry_session')
439        if entry_session == self.getSessionId()[-2:]:
440            wfaction = 'admit'
441            wft = 'wf_transition_admit'
442            password = None
443        else:
444            wfaction = 'return'
445            wft = 'wf_transition_return'
446            password = self.generatePassword()
447            self.makeStudentMember(sid,password)
448
449        for pt in f2t.keys():
450            student_obj.invokeFactory(pt,f2t[pt]['id'])
451            sub_obj = getattr(student_obj,f2t[pt]['id'])
452            sub_doc = sub_obj.getContent()
453            #self.portal_workflow.doActionFor(sub_obj,'open',dest_container=sub_obj)
454            d['Title'] = f2t[pt]['title']
455            for field in f2t[pt]['fields']:
456                d[field] = dict.get(field,'')
457            sub_doc.edit(mapping = d)
458            new_state = f2t[pt][wft]
459            if new_state != "remain":
460                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
461        self.portal_workflow.doActionFor(student_obj,wfaction)
462        student_obj.manage_setLocalRoles(sid, ['Owner',])
463        return sid,password
464    ###)
465
466    security.declarePublic('getCertificateBrain') ###(
467    def getCertificateBrain(self,cert_id):
468        "do it"
469        res = ZCatalog.searchResults(self.portal_catalog_real,
470                                {'portal_type':"Certificate",
471                                      'id': cert_id})
472        if res:
473            return res[0]
474        return None
475    ###)
476
477    security.declareProtected(ModifyPortalContent,'get_csv_filenames') ###(
478    def get_csv_filenames(self):
479        "do it"
480        files = [file for file in os.listdir("%s/import/" % (i_home))
481                 if file.endswith('.csv') and file.find('imported') == -1]
482        return files
483    ###)
484
485    security.declarePublic('findStudentByMatricelNo') ###(
486    def findStudentByMatricelNo(self,matric_no):
487        "do it"
488        res = ZCatalog.searchResults(self.portal_catalog_real,
489                                {'portal_type':"StudentClearance",
490                                 'SearchableText': matric_no})
491        if res:
492            return res[0]
493        return None
494    ###)
495
496    security.declarePublic('makeStudentMember') ###(
497    def makeStudentMember(self,sid,password='uNsEt'):
498        """make the student a member"""
499        membership = self.portal_membership
500        membership.addMember(sid,
501                             password ,
502                             roles=('Member',
503                                     'Student',
504                                     ),
505                             domains='',
506                             properties = {'memberareaCreationFlag': False,
507                                           'homeless': True},)
508        member = membership.getMemberById(sid)
509        self.portal_registration.afterAdd(member, sid, password, None)
510        #self.manage_setLocalRoles(sid, ['Owner',])
511    ###)
512
513    security.declarePublic('makeStudentData') ###(
514    def makeStudentData(self,student_id,email=None,phone_nr=None):
515        "create Datastructure for a returning Student"
516        #import pdb;pdb.set_trace()
517        logger = logging.getLogger('WAeUPTool.makeStudentData')
518        students_folder = self.portal_url.getPortalObject().campus.students
519        #res = self.students_catalog(id=student_id)
520        #if res:
521        #    st = res[0]
522        #res = self.returning_import(matric_no = st.matric_no)
523        res = self.returning_import(id = student_id)
524        if res:
525            student = res[0]
526        else:
527            logger.info('Id %s not found in returning_import' % student_id)
528            return
529        logger.info('%s creates data structure' % student_id)
530        s_results = self.results_import(matric_no = student.matric_no)
531        if s_results:
532            lnr = self.getLevelFromResultsCosCode(s_results)
533            level = "%d00" % lnr
534            verdict,eligible = self.getVerdict(s_results[0].Verdict)
535            if eligible:
536                level = "%d00" % (lnr + 1)
537        else:
538            logger.info('matric_no %s not found in results_import' % student.matric_no)
539            level = 0
540            verdict = 'N/A'
541        #student should not be allowed to perform this transition
542        #wftool = self.portal_workflow
543        #wftool.doActionFor(student,'return')
544        certcode_org = student.Coursemajorcode
545        certcode = makeCertificateCode(certcode_org)
546        certificate_brain = self.getCertificateBrain(certcode)
547        if not certificate_brain:
548            em = 'Certificate %s org-code %s not found\n' % (certcode, certcode_org)
549            logger.info(em)
550        matric_no = student.matric_no
551        sid = student_id
552        student_obj = getattr(students_folder,sid)
553        student_obj.invokeFactory('StudentApplication','application')
554        application = student_obj.application
555        self.portal_workflow.doActionFor(application,'open',dest_container=application)
556        da = {'Title': 'Application Data'}
557        student_obj.invokeFactory('StudentPersonal','personal')
558        da['jamb_reg_no'] = student.Entryregno
559        em = self.getEntryMode(student.Entryregno)
560##        em = student.Mode_of_Entry
561##        if em in ('DIRECT', 'DIRECT ENTRY',):
562##            em = 'DE'
563##        elif em in ('U.M.E', 'UNE',):
564##            em = 'UME'
565##        elif not em:
566##            em = "unknown"
567        da['entry_mode'] = em
568        personal = student_obj.personal
569        self.portal_workflow.doActionFor(personal,'open',dest_container=personal)
570        dp = {'Title': 'Personal Data'}
571        student_obj.invokeFactory('StudentClearance','clearance')
572        clearance = student_obj.clearance
573        self.portal_workflow.doActionFor(clearance,'open',dest_container=clearance)
574        dc = {'Title': 'Clearance/Eligibility Record'}
575        dc['matric_no'] = matric_no
576        state = student.State
577        lga = student.LGA
578        if state and lga:
579            lga =  state + ' / ' + lga
580        else:
581            lga = "None"
582        da['jamb_lga'] = dc['lga'] = lga
583        da['app_email'] = dp['email'] = email
584        da['app_mobile'] = dp['phone'] = phone_nr
585        dp['firstname'] = student.Firstname
586        dp['middlename'] = student.Middlename
587        dp['lastname'] = student.Lastname
588        da['jamb_lastname'] = "%s %s %s" % (student.Firstname,student.Middlename,student.Lastname)
589        da['jamb_sex'] = student.Sex
590        dp['sex'] = student.Sex == 'F'
591        dp['perm_address'] = student.Permanent_Address
592        application.getContent().edit(mapping=da)
593        self.portal_workflow.doActionFor(application,'close',dest_container=application)
594        personal.getContent().edit(mapping=dp)
595        clearance.getContent().edit(mapping=dc)
596        self.portal_workflow.doActionFor(clearance,'close',dest_container=clearance)
597##        catd = {}
598##        catd['id'] = sid
599##        catd['entry_mode']= da['entry_mode']
600##        catd['matric_no'] = matric_no
601##        catd['jamb_reg_no'] = da['jamb_reg_no']
602##        catd['name'] = "%(firstname)s %(middlename)s %(lastname)s" % dp
603##        catd['sex'] = dp['sex']
604##        catd['level'] = level
605##        catd['verdict'] = verdict
606##        if certificate_brain:
607##            cpath = certificate_brain.getPath().split('/')
608##            catd['faculty'] = cpath[-4]
609##            catd['department'] = cpath[-3]
610##            catd['course'] = certcode
611##        self.students_catalog.modifyRecord(**catd)
612        #
613        # Study Course
614        #
615        student_obj.invokeFactory('StudentStudyCourse','study_course')
616        studycourse = student_obj.study_course
617        self.portal_workflow.doActionFor(studycourse,'open',dest_container=studycourse)
618        dsc = {}
619        dsc['study_course'] = certcode
620        dsc['current_level'] = level
621        dsc['current_verdict'] = verdict
622        dsc['current_mode'] = em
623        dsc['current_session'] = '06'
624        studycourse.getContent().edit(mapping=dsc)
625        #
626        # Level
627        #
628##        l = getattr(studycourse,level,None)
629##        if l is None:
630##            studycourse.invokeFactory('StudentStudyLevel', level)
631##            l = getattr(studycourse, level)
632##            self.portal_workflow.doActionFor(l,'open',dest_container=l)
633##            l.getContent().edit(mapping={'Title': "Level %s" % level})
634###)
635
636    security.declarePublic('makeStudentLevel') ###(
637    def makeStudentLevel(self,student_id):
638        "create the StudyLevel for a returning Student"
639        #import pdb;pdb.set_trace()
640        logger = logging.getLogger('WAeUPTool.makeStudentLevel')
641        students_folder = self.portal_url.getPortalObject().campus.students
642        res = self.students_catalog(id=student_id)
643        if res:
644            st = res[0]
645        course = st.course
646        matric_no = st.matric_no
647        level = st.level
648        res = self.results_import(matric_no = matric_no)
649        if res:
650            results = res
651        logger.info('%s creating Level %s' % (student_id,level))
652        #
653        # Level
654        #
655        student_obj = getattr(self.portal_url.getPortalObject().campus.students,student_id)
656        studycourse = getattr(student_obj,"study_course",None)
657        self.portal_workflow.doActionFor(studycourse,'close_for_edit',dest_container=studycourse)
658        l = getattr(studycourse,level,None)
659        if l is None:
660            studycourse.invokeFactory('StudentStudyLevel', level)
661            l = getattr(studycourse, level)
662            self.portal_workflow.doActionFor(l,'open',dest_container=l)
663            l.getContent().edit(mapping={'Title': "Level %s" % level})
664        ###)
665
666    security.declarePublic('getHallInfo') ###(
667    def getHallInfo(self,bed):
668        """return Hall Info"""
669        info = {}
670        hall,block,room,letter = bed.split('_')
671        res = ZCatalog.searchResults(self.portal_catalog_real,portal_type="AccoHall",id=hall)
672        if res and len(res) == 1:
673            hall_brain = res[0]
674            hall_doc = hall_brain.getObject().getContent()
675        else:
676            return info
677        info['hall_title'] = hall_brain.Title
678        info['maintenance_code'] = hall_doc.maintenance_code
679        res = ZCatalog.searchResults(self.portal_catalog_real,portal_type="ScratchCardBatch")
680        batch_doc = None
681        for brain in res:
682            if brain.id.startswith(info['maintenance_code']):
683                batch_doc = brain.getObject().getContent()
684                break
685        if batch_doc is None:
686            info['maintenance_fee'] = None
687        else:
688            info['maintenance_fee'] = batch_doc.cost
689        return info
690    ###)
691
692    security.declarePublic('picturesExist') ###(
693    def picturesExist(self, ids):
694        """check if pictures exist in the filesystem"""
695        path = 'images'
696        student_id = self.getStudentId()
697        picture_path = os.path.join(i_home,path,student_id)
698        if not os.path.exists(picture_path):
699            return False
700        pictures  = [picture[:picture.rfind('_')] for picture in os.listdir(picture_path)]
701        return set(ids).issubset(set(pictures))
702    ###)
703
704    security.declarePublic('picturesList') ###(
705    def picturesList(self):
706        """check if pictures exist in the filesystem"""
707        path = 'images'
708        student_id = self.getStudentId()
709        picture_path = os.path.join(i_home,path,student_id)
710        if not os.path.exists(picture_path):
711            return []
712        return [picture[:picture.rfind('_')] for picture in os.listdir(picture_path)]
713    ###)
714
715    security.declarePublic('showFsPicture') ###(
716    def showFsPicture(self,path):
717        """return a picture from the filesystem"""
718        picture_path = os.path.join(i_home,path)
719        response = self.REQUEST.RESPONSE
720        #import pdb;pdb.set_trace()
721        registry = getToolByName(self, 'mimetypes_registry')
722        mimetype = str(registry.lookupExtension(path.lower()) or
723                    registry.lookupExtension('file.bin'))
724        if os.path.exists(picture_path):
725            response.setHeader('Content-type',mimetype)
726            return open(picture_path).read()
727        picture_path = os.path.join(i_home,'import',path)
728        if os.path.exists(picture_path):
729            return open(picture_path).read()
730    ###)
731
732    security.declareProtected(ModifyPortalContent,'deleteAllCourses') ###(
733    def deleteAllCourses(self,department="All"):
734        ''' delete the courses'''
735        pm = self.portal_membership
736        member = pm.getAuthenticatedMember()
737
738        if str(member) not in ("henrik","joachim"):
739            return "not possible"
740        if department == "All":
741            res = self.portal_catalog({'meta_type': 'Department'})
742        if len(res) < 1:
743            return "No Departments found"
744
745        deleted = []
746        for dep in res:
747            cf = dep.getObject().courses
748            if cf:
749                cf.manage_delObjects(ids=cf.objectIds())
750                deleted.append("deleted Courses in %s" % dep.getId)
751        return "\r".join(deleted)
752    ###)
753
754    security.declareProtected(ModifyPortalContent,'getLogfileLines') ###(
755    def getLogfileLines(self,filename="event.log",numlines=20):
756        """Get last NUMLINES lines of logfile FILENAME.
757
758        Return last lines' of a file in the instances logfile directory as
759        a list. The number of returned lines equals `numlines' or less. If
760        less than `numlines' lines are available, the whole file ist
761        returned. If the file can not be opened or some other error
762        occurs, empty list is returend.
763        """
764        result = []
765        lines_hit = 0
766
767        # We only handle files in instances' log directory...
768        logpath = os.path.join(i_home, "log")
769        filename = str(os.path.abspath( os.path.join( logpath, filename )))
770        if not filename.startswith( logpath ):
771            # Attempt to access file outside log-dir...
772            return []
773
774        try:
775            fd = file( filename, "rb" )
776        except IOError:
777            return []
778        if not fd:
779            return []
780
781        if os.linesep == None:
782            linesep = '\n'
783        else:
784            linesep = os.linesep
785
786        # Try to find 'numlines' times a lineseparator, searching from end
787        # and moving to the beginning of file...
788        fd.seek( 0, 2) # Move to end of file...
789        while lines_hit < numlines:
790            if fd.read(1) == linesep[-1]: # This moves filedescriptor
791                                          # one step forward...
792                lines_hit += 1
793            try:
794                fd.seek( -2, 1) # Go two bytes back from current pos...
795            except IOError:
796                # We cannot go back two bytes. Maybe the file is too small...
797                break
798        fd.seek(2,1)
799
800        # Read all lines from current position...
801        result = fd.readlines()
802        # Remove line endings...
803        result = [x.strip() for x in result]
804        fd.close()
805        return result
806    ###)
807
808    security.declareProtected(ModifyPortalContent,"getCallbacksFromLog")###(
809    def getCallbacksFromLog(self,filename):
810        """fix Online Payment Transactions from Z2.log entries"""
811        import transaction
812        import random
813        from cgi import parse_qs
814        from urlparse import urlparse
815        #from pdb import set_trace
816        wftool = self.portal_workflow
817        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
818        students_folder = self.portal_url.getPortalObject().campus.students
819        s = r'(?P<client_ip>\S+) - (?P<member_id>\S+) \['
820        s += r'(?P<date>.*)\] "(?P<get>.*)" (?P<codes>\d+ \d+) "'
821        s += r'(?P<intersw>.*)" "(?P<agent>.*)"'
822        data = re.compile(s)
823        start = True
824        tr_count = 1
825        total = 0
826        #name = 'pume_results'
827        #name = 'epaymentsuccessful_z2log2'
828        name = filename
829        no_import = []
830        imported = []
831        logger = logging.getLogger('WAeUPTool.getFailedTransactions')
832        try:
833            transactions = open("%s/import/%s" % (i_home,name),"rb").readlines()
834        except:
835            logger.error('Error reading %s' % name)
836            return
837        tas = []
838        for line in transactions:
839            dict = {}
840            items = data.search(line)
841            dict['idict'] = idict = items.groupdict()
842            #print idict
843            #from pdb import set_trace;set_trace()
844            urlparsed = urlparse(idict['get'][4:])
845            #print urlparsed
846            path = urlparsed[2].split('/')
847            dict['student_id'] = student_id = path[8]
848            dict['payment_id'] = payment_id = path[10]
849            dict['qs_dict'] = qs_dict = parse_qs(urlparsed[4])
850            tas.append(dict)
851            tr_count += 1
852        return tas
853    ###)
854
855    security.declareProtected(ModifyPortalContent,"importOnlinePaymentTransactions")###(
856    def importOnlinePaymentTransactions(self):
857        """load Online Payment Transactions from CSV values"""
858        import transaction
859        import random
860        #from pdb import set_trace
861        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
862        opt = self.online_payments_import
863        students_folder = self.portal_url.getPortalObject().campus.students
864        start = True
865        tr_count = 1
866        total = 0
867        #name = 'pume_results'
868        name = 'OnlineTransactions'
869        no_import = []
870        imported = []
871        logger = logging.getLogger('WAeUPTool.importOnlinePaymentTransactions')
872        try:
873            transactions = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
874        except:
875            logger.error('Error reading %s.csv' % name)
876            return
877        for pay_transaction in transactions:
878            if start:
879                start = False
880                logger.info('Start loading from %s.csv' % name)
881                s = ','.join(['"%s"' % fn for fn in pay_transaction.keys()])
882                no_import.append('%s,"Error"' % s)
883                format = ','.join(['"%%(%s)s"' % fn for fn in pay_transaction.keys()])
884                format_error = format + ',"%(Error)s"'
885            data = {}
886
887            # format of the first file sent by Tayo
888            #data['datetime'] = date = DateTime.DateTime(pay_transaction['Date'])
889            #data['student_id'] = student_id = pay_transaction['Payer ID']
890            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
891            #data['response_code'] = response_code = pay_transaction['Resp Code']
892            #data['amount'] = amount = pay_transaction['Amount']
893
894            # format of the second file sent by Tayo
895            #data['datetime'] = date = 0
896            #data['student_id'] = student_id = pay_transaction['Payer ID']
897            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
898            #data['response_code'] = response_code = '00'
899            #data['amount'] = amount = pay_transaction['Amount']
900
901            # format of the third file sent by Kehinde
902            data['datetime'] = date = 0
903            data['student_id'] = student_id = pay_transaction['customer_id']
904            data['order_id'] = order_id = pay_transaction['merchant_reference']
905            data['response_code'] = response_code = '00'
906            data['amount'] = amount = pay_transaction['Amount']
907
908            dup = False
909            if response_code == "12":
910                continue
911            try:
912                opt.addRecord(**data)
913            except ValueError:
914                dup = True
915            #from pdb import set_trace;set_trace()
916            if dup:
917                if response_code == "00":
918                    try:
919                        opt.modifyRecord(**data)
920                    except:
921                        logger.info("duplicate uid, order_id %(order_id)s, student_id %(student_id)s, response_code %(response_code)s" % data)
922                        continue
923                else:
924                    pay_transaction['Error'] = "Duplicate order_id"
925                    no_import.append( format_error % pay_transaction)
926                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
927                    continue
928            tr_count += 1
929            if tr_count > 1000:
930                if len(no_import) > 0:
931                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
932                             '\n'.join(no_import) + '\n')
933                    no_import = []
934                em = '%d transactions committed\n' % (tr_count)
935                transaction.commit()
936                regs = []
937                logger.info(em)
938                total += tr_count
939                tr_count = 0
940        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
941                                                '\n'.join(no_import))
942        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
943    ###)
944
945    security.declareProtected(ModifyPortalContent,'mass_create_faculty') ###(
946    def mass_create_faculty(self,mapping):
947        "create a faculty"
948        logger = logging.getLogger('WAeUPTool.mass_create_faculty')
949        academics_folder = self.portal_url.getPortalObject().campus.academics
950        fid = mapping['code']
951        if getattr(academics_folder,fid,None) is not None:
952            return '', "Faculty with ID: %s exists" % fid
953        logger.info('Creating Faculty %(code)s, %(title)s' % mapping)
954        try:
955            academics_folder.invokeFactory('Faculty', fid)
956        except BadRequest,E:
957            return '', "%s" % E
958        f = getattr(academics_folder,fid,None)
959        f.getContent().edit(mapping=mapping)
960        return fid,''
961    ###)
962
963    security.declareProtected(ModifyPortalContent,'mass_edit_faculty') ###(
964    def mass_edit_faculty(self,mapping):
965        "edit a faculty"
966        logger = logging.getLogger('WAeUPTool.mass_edit_faculty')
967        academics_folder = self.portal_url.getPortalObject().campus.academics
968        fid = mapping['code']
969        f = getattr(academics_folder,fid,None)
970        if f is None:
971            return '', "Faculty with ID: %s does not exist" % fid
972        logger.info('Editing Faculty %(code)s, %(title)s' % mapping)
973        f.getContent().edit(mapping=mapping)
974        return fid,''
975    ###)
976
977    security.declareProtected(ModifyPortalContent,'mass_create_department') ###(
978    def mass_create_department(self,mapping):
979        "create a department in the correct faculty"
980        logger = logging.getLogger('WAeUPTool.mass_create_department')
981        fid = mapping['faculty_code']
982        if getattr(self,'_v_faculties',None) is None:
983            res = self.portal_catalog(portal_type = "Faculty")
984            self._v_faculties = {}
985            for f in res:
986                self._v_faculties[f.getId] = f.getObject()
987        f = self._v_faculties.get(fid,None)
988        if f is None:
989            return '', "No Faculty with ID: %s" % fid
990        else:
991            did = mapping.get('code')
992            d = getattr(f,did,None)
993            if d is None or d.portal_type == "Faculty":
994                logger.info('Creating Department %(code)s, %(title)s' % mapping)
995                try:
996                    f.invokeFactory('Department', did)
997                except BadRequest,E:
998                    return '', "%s" % E
999                d = getattr(f,did)
1000                d.invokeFactory('CoursesFolder','courses')
1001                courses = getattr(d,'courses')
1002                dict = {'Title': 'Courses'}
1003                courses.getContent().edit(mapping=dict)
1004                d.invokeFactory('CertificatesFolder','certificates')
1005                certificates = getattr(d,'certificates')
1006                dict = {'Title': 'Certificates'}
1007                certificates.getContent().edit(mapping=dict)
1008            d.getContent().edit(mapping=mapping)
1009        return did,''
1010    ###)
1011
1012    security.declareProtected(ModifyPortalContent,'mass_edit_department') ###(
1013    def mass_edit_department(self,mapping):
1014        "create a department in the correct faculty"
1015        logger = logging.getLogger('WAeUPTool.mass_create_department')
1016        academics_folder = self.portal_url.getPortalObject().campus.academics
1017        fid = mapping['faculty_code']
1018        did = mapping.get('code')
1019        try:
1020            d = getattr(getattr(academics_folder,fid),did,None)
1021        except KeyError:
1022            return '', "Department %s or Faculty %s wrong" % (did,fid)
1023        else:
1024            if d is None or d.portal_type == "Faculty":
1025                logger.info('Editing Department %(code)s, %(title)s' % mapping)
1026            d.getContent().edit(mapping=mapping)
1027        return did,''
1028    ###)
1029
1030    security.declareProtected(ModifyPortalContent,'mass_create_course') ###(
1031    def mass_create_course(self,mapping):
1032        #import pdb;pdb.set_trace()
1033        if getattr(self,'_v_course_list',None) is None:
1034            self._v_course_list = []
1035        if getattr(self,'_v_departments',None) is None:
1036            res = self.portal_catalog(portal_type = "Department")
1037            self._v_department_courses = {}
1038            for d in res:
1039                self._v_department_courses[d.getId] = getattr(d.getObject(),"courses",None)
1040        did = mapping['department_code']
1041        d = self._v_department_courses.get(did,None)
1042        if d is None:
1043            return '', "No Department with ID: %s" % did
1044        course_id = mapping.get('code')
1045        if course_id in self._v_course_list:
1046            return '', "Duplicate Course ID: %s" % did
1047        c = getattr(d,course_id,None)
1048        if c is not None:
1049            return '', "Duplicate Course ID: %s" % did
1050        try:
1051            d.invokeFactory('Course', course_id)
1052        except BadRequest,E:
1053            return '', "%s" % E
1054        self._v_course_list.append(course_id)
1055        c = getattr(d,course_id)
1056        c.getContent().edit(mapping=mapping)
1057        return course_id,''
1058    ###)
1059
1060    security.declareProtected(ModifyPortalContent,'mass_edit_course') ###(
1061    def mass_edit_course(self,mapping):
1062        #import pdb;pdb.set_trace()
1063        course_id = mapping.get('code')
1064        res = self.portal_catalog(id=course_id)
1065        if not res:
1066            return '', "No Course with ID: %s" % course_id
1067        c = res[0].getObject()
1068        c.getContent().edit(mapping=mapping)
1069        return course_id,''
1070    ###)
1071
1072    security.declareProtected(ModifyPortalContent,'mass_create_certificate') ###(
1073    def mass_create_certificate(self,mapping):
1074        if getattr(self,'_v_certificate_list',None) is None:
1075            self._v_certificate_list = []
1076        if getattr(self,'_v_department_certificates',None) is None:
1077            res = self.portal_catalog(portal_type = "Department")
1078            self._v_department_certificates = {}
1079            for d in res:
1080                self._v_department_certificates[d.getId] = getattr(d.getObject(),"certificates",None)
1081        did = mapping['department_code']
1082        d = self._v_department_certificates.get(did,None)
1083        if d is None:
1084            return '', "No Department with ID: %s" % did
1085        certificate_id = mapping.get('code')
1086        if certificate_id in self._v_certificate_list:
1087            return '', "Duplicate Certificate ID: %s" % did
1088        c = getattr(d,certificate_id,None)
1089        if c is not None:
1090            return '', "Duplicate Certificate ID: %s" % did
1091        try:
1092            d.invokeFactory('Certificate', certificate_id)
1093        except BadRequest,E:
1094            return '', "%s" % E
1095        self._v_certificate_list.append(certificate_id)
1096        c = getattr(d,certificate_id)
1097        c.getContent().edit(mapping=mapping)
1098        return certificate_id,''
1099    ###)
1100
1101    security.declareProtected(ModifyPortalContent,'mass_edit_certificate') ###(
1102    def mass_edit_certificate(self,mapping):
1103        #import pdb;pdb.set_trace()
1104        certificate_id = mapping.get('code')
1105        res = self.portal_catalog(id=certificate_id)
1106        if not res:
1107            return '', "No Certificate with ID: %s" % did
1108        c = res[0].getObject()
1109        c.getContent().edit(mapping=mapping)
1110        return certificate_id,''
1111    ###)
1112
1113    security.declareProtected(ModifyPortalContent,'mass_create_certificate_course') ###(
1114    def mass_create_certificate_course(self,mapping):
1115        if getattr(self,'_v_courses',None) is None:
1116            res = self.courses_catalog()
1117            self._v_courses= [course.code for course in res]
1118        if getattr(self,'_v_ceritficates',None) is None:
1119            res = self.portal_catalog(portal_type = "Certificate")
1120            self._v_certificates = {}
1121            for cert in res:
1122                self._v_certificates[cert.getId] = cert.getObject()
1123        certificate_course_id = mapping.get('code')
1124        if certificate_course_id not in self._v_courses:
1125            return '', "No Course with ID: %s" % certificate_course_id
1126        cert_id = mapping['certificate_code']
1127        cert = self._v_certificates.get(cert_id,None)
1128        if cert is None:
1129            return '', "No Certificate with ID: %s" % cert_id
1130        level_id = mapping.get('level')
1131        level = getattr(cert,level_id,None)
1132        if level is None:
1133            cert.invokeFactory('StudyLevel', level_id)
1134            level = getattr(cert,level_id,None)
1135        elif hasattr(level,certificate_course_id):
1136            return '', "Duplicate CertificateCourse ID: %s in %s/ %s" %\
1137            (certificate_course_id,cert_id,level_id)
1138        level.invokeFactory('CertificateCourse', certificate_course_id)
1139        c = getattr(level,certificate_course_id)
1140        c.getContent().edit(mapping=mapping)
1141        return certificate_course_id,''
1142    ###)
1143
1144    field2types_student = {   ###(
1145                      'StudentApplication':
1146                          {'id': 'application',
1147                           'title': 'Application Data',
1148                           'wf_transition_return': 'close',
1149                           'wf_transition_admit': 'remain',
1150                           'fields':
1151                             ('jamb_reg_no',
1152                              'entry_mode',
1153                              'entry_session',
1154                              'jamb_score',
1155                              'app_email',
1156                              'jamb_age',
1157                              #'jamb_state',
1158                              #'jamb_lga',
1159                              )
1160                              },
1161                      #'StudentPume':
1162                      #    {'id': 'pume',
1163                      #     'title': 'Pume Data',
1164                      #     'wf_transition_return': 'close',
1165                      #     'wf_transition_admit': 'close',
1166                      #     'fields':
1167                      #       ('pume_score',
1168                      #        )
1169                      #        },
1170                      'StudentClearance':
1171                          {'id': 'clearance',
1172                           'title': 'Clearance/Eligibility Record',
1173                           'wf_transition_return': 'close',
1174                           'wf_transition_admit': 'remain',
1175                           'fields':
1176                             ('matric_no',
1177                              'nationality',
1178                              'lga',
1179                              'birthday',
1180                              )
1181                              },
1182                         'StudentPersonal':
1183                          {'id': 'personal',
1184                           'title': 'Personal Data',
1185                           'wf_transition_return': 'open',
1186                           'wf_transition_admit': 'remain',
1187                           'fields':
1188                             ('firstname',
1189                              'middlename',
1190                              'lastname',
1191                              'sex',
1192                              'email',
1193                              'phone',
1194                              'perm_address',
1195                              )
1196                              },
1197                         'StudentStudyCourse':
1198                          {'id': 'study_course',
1199                           'title': 'Study Course',
1200                           'wf_transition_return': 'open',
1201                           'wf_transition_admit': 'remain',
1202                           'fields':
1203                             ('study_course',
1204                              'current_level',
1205                              'current_session',
1206                              'current_mode',
1207                              'current_verdict',
1208                              )
1209                              },
1210
1211                         'PaymentsFolder':
1212                          {'id': 'payments',
1213                           'title': 'Payments',
1214                           'wf_transition_return': 'open',
1215                           'wf_transition_admit': 'open',
1216                           'fields':
1217                             ()
1218                              },
1219                         }
1220    ###)
1221
1222    security.declareProtected(ModifyPortalContent,'mass_create_student') ###(
1223    def mass_create_student(self,mapping):
1224        "create a students record due import"
1225        logger = logging.getLogger('WAeUPTool.mass_create_student')
1226        students_folder = self.portal_url.getPortalObject().campus.students
1227        jamb_reg_no = mapping.get('jamb_reg_no',None)
1228        if jamb_reg_no:
1229            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1230            if res:
1231                return '',"jamb_reg_no exists"
1232        matric_no = mapping.get('matric_no',None)
1233        if matric_no:
1234            res = self.students_catalog(matric_no = matric_no)
1235            if res:
1236                return '',"matric_no exists"
1237        sid = self.waeup_tool.generateStudentId('?')
1238        students_folder.invokeFactory('Student', sid)
1239        student_obj = getattr(students_folder,sid)
1240        f2t = self.field2types_student
1241        d = {}
1242        d['jamb_sex']  = 'M'
1243        if mapping.get('sex'):
1244            d['jamb_sex']  = 'F'
1245        transition = mapping.get('reg_transition','admit')
1246        if transition not in ('admit','return'):
1247            return '',"no valid transition provided"
1248        for pt in f2t.keys():
1249            student_obj.invokeFactory(pt,f2t[pt]['id'])
1250            sub_obj = getattr(student_obj,f2t[pt]['id'])
1251            sub_doc = sub_obj.getContent()
1252            d['Title'] = f2t[pt]['title']
1253            for field in f2t[pt]['fields']:
1254                d[field] = mapping.get(field,'')
1255            if pt == "StudyCourse":
1256                for von,zu in (('entry_mode','current_mode'),
1257                               ('entry_session','current_session')):
1258                    if mapping.get(zu,None) is None and mapping.get(von,None) is not None:
1259                        d[zu] = mapping[von]
1260            sub_doc.edit(mapping = d)
1261
1262            #import pdb;pdb.set_trace()
1263            new_state = f2t[pt]['wf_transition_%(transition)s' % vars()]
1264            if new_state != "remain":
1265                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1266        self.portal_workflow.doActionFor(student_obj,transition)
1267        student_obj.manage_setLocalRoles(sid, ['Owner',])
1268        return sid,''
1269    ###)
1270
1271    security.declareProtected(ModifyPortalContent,'mass_edit_student') ###(
1272    def mass_edit_student(self,mapping):
1273        "edit a students record due import"
1274        logger = logging.getLogger('WAeUPTool.mass_edit_student')
1275        students_folder = self.portal_url.getPortalObject().campus.students
1276        sid = mapping.get('id',None)
1277        jamb_reg_no = mapping.get('jamb_reg_no',None)
1278        matric_no = mapping.get('matric_no',None)
1279        editable_keys = mapping.keys()
1280        if sid:
1281            res = self.students_catalog(id = sid)
1282            if not res:
1283                return '',"no student with id %s" % sid
1284            if matric_no and res[0].matric_no and\
1285              matric_no != res[0].matric_no:
1286                logger.info("%s, old matric_no %s overwritten with %s" % (res[0].id,res[0].matric_no,matric_no))
1287            if jamb_reg_no and res[0].jamb_reg_no and\
1288              jamb_reg_no != res[0].jamb_reg_no:
1289                logger.info("%s, old reg_no %s overwritten with %s" % (res[0].id,res[0].jamb_reg_no,jamb_reg_no))
1290        elif jamb_reg_no:
1291            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1292            if not res:
1293                return '',"no student with jamb_reg_no %s" % jamb_reg_no
1294            editable_keys.remove('jamb_reg_no')
1295        elif matric_no:
1296            res = self.students_catalog(matric_no = matric_no)
1297            if not res:
1298                return '',"no student with matric_no %s" % matric_no
1299            editable_keys.remove('matric_no')
1300
1301        ## included only to change wf state from admitted to returning
1302        #if res[0].review_state not in ('admitted','objection_raised'):
1303        #    return '%s' % res[0].id ,"student is not in state admitted or objection_raised"
1304        ## end inclusion
1305
1306        sid = res[0].id
1307        student_obj = getattr(students_folder,sid)
1308        f2t = self.field2types_student
1309        d = {}
1310        #import pdb;pdb.set_trace()
1311        any_change = False
1312        for pt in f2t.keys():
1313            if pt == "student_application":
1314                d['jamb_sex']  = 'M'
1315                if mapping.get('sex'):
1316                    d['jamb_sex']  = 'F'
1317            intersect = set(f2t[pt]['fields']).intersection(set(editable_keys))
1318            if intersect:
1319                sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1320                if sub_obj is None:
1321                    try:
1322                        student_obj.invokeFactory(pt,f2t[pt]['id'])
1323                    except:
1324                        continue
1325                    sub_obj = getattr(student_obj,f2t[pt]['id'])
1326                    d['Title'] = f2t[pt]['title']
1327                sub_doc = sub_obj.getContent()
1328                for field in intersect:
1329                    changed = False
1330                    if getattr(sub_doc,field) != mapping.get(field,''):
1331                        any_change = True
1332                        changed = True
1333                        d[field] = mapping.get(field,'')
1334                    if changed:
1335                        sub_doc.edit(mapping = d)
1336
1337
1338        ## included only to change wf state from admitted to returning
1339        #    if res[0].review_state in ('admitted','objection_raised'):
1340        #        new_state = f2t[pt]['wf_transition_return']
1341        #        sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1342        #        if sub_obj and new_state != "remain":
1343        #            try:
1344        #                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1345        #            except:
1346        #                #logger.info('%s, wf transition %s of %s failed' % (sid,new_state,sub_obj.id))
1347        #                pass
1348        #if res[0].review_state in ('admitted','objection_raised'):
1349        #    wfaction = 'return'
1350        #    try:
1351        #        self.portal_workflow.doActionFor(student_obj,wfaction)
1352        #        logger.info('%s, wf state changed' % sid)
1353        #        any_change = True
1354        #    except:
1355        #        logger.info('%s, wf transition failed, old state = %s' % (sid,res[0].review_state))
1356        #        pass
1357        ## end inclusion
1358
1359
1360        if any_change:
1361            return sid,''
1362        else:
1363            return sid,'not modified'
1364    ###)
1365
1366    security.declareProtected(ModifyPortalContent,"importData")###(
1367    def importData(self,filename,name,edit=False,bypass_queue_catalog=False):
1368        """load data from CSV values"""
1369        import transaction
1370        import random
1371
1372        pm = self.portal_membership
1373        member = pm.getAuthenticatedMember()
1374
1375        logger = logging.getLogger('WAeUPTool.importData')
1376        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1377        students_folder = self.portal_url.getPortalObject().campus.students
1378        start = True
1379        tr_count = 1
1380        total_imported = 0
1381        total_not_imported = 0
1382        total = 0
1383        iname = "import_%s" % name
1384        stool = getToolByName(self, 'portal_schemas')
1385        ltool = getToolByName(self, 'portal_layouts')
1386        schema = stool._getOb(iname)
1387        if schema is None:
1388            em = 'No such schema %s' % iname
1389            logger.error('No such schema %s' % iname)
1390            return em
1391        layout = ltool._getOb(iname)
1392        if layout is None:
1393            em = 'No such layout %s' % iname
1394            logger.error(em)
1395            return em
1396        validators = {}
1397        for widget in layout.keys():
1398            validators[widget] = layout[widget].validate
1399        #import pdb;pdb.set_trace()
1400        mode = "create"
1401        if edit:
1402            mode = "edit"
1403        importer_name = "mass_%(mode)s_%(name)s" % vars()
1404        importer = getattr(self, '%s' % importer_name,None)
1405        if importer is None:
1406            em = 'No importer function %s' % importer_name
1407            logger.error(em)
1408            return em
1409        not_imported = []
1410        imported = []
1411        try:
1412            items = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
1413        except:
1414            em = 'Error reading %s.csv' % filename
1415            logger.error(em)
1416            return em
1417        for item in items:
1418            if start:
1419                start = False
1420                adapters = [MappingStorageAdapter(schema, item)]
1421                logger.info('%s starts import from %s.csv in %s mode with schema and layout %s' % (member,filename,mode,iname))
1422                attrs = csv.reader(open("%s/import/%s.csv" % (i_home,filename),"rb")).next()
1423                import_keys = [k for k in attrs if not k.startswith('ignore')]
1424                diff2schema = set(import_keys).difference(set(schema.keys()))
1425                diff2layout = set(import_keys).difference(set(layout.keys()))
1426                if diff2schema:
1427                    em = 'not ignorable key(s): "%s" found in heading' % ", ".join(diff2schema)
1428                    return em
1429                s = ','.join(['"%s"' % fn for fn in import_keys])
1430                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(s + ',"Error"'+ '\n')
1431                s = '"id",' + s
1432                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
1433                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
1434                format_error = format + ',"%(Error)s"'
1435                format = '"%(id)s",'+ format
1436
1437            dm = DataModel(item, adapters,context=self)
1438            ds = DataStructure(data=item,datamodel=dm)
1439            error_string = ""
1440            for k in import_keys:
1441                #import pdb;pdb.set_trace()
1442                if not validators[k](ds,mode=mode):
1443                    error_string += " %s : %s" % (k,
1444                                                  self.translation_service(ds.getError(k),
1445                                                                           ds.getErrorMapping(k)))
1446            if not error_string:
1447                item.update(dm)
1448                item['id'],error = importer(item)
1449                if error:
1450                    error_string += error
1451            if error_string:
1452                item['Error'] = error_string
1453                not_imported.append(format_error % item)
1454                total_not_imported += 1
1455            else:
1456                em = format % item
1457                imported.append(em)
1458                logger.info("%(total_imported)d of %(total)d %(em)s" % vars())
1459                tr_count += 1
1460                total_imported += 1
1461            total += 1
1462            if total and not total % 100:
1463                transaction.commit()
1464                if len(not_imported) > 0:
1465                    open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1466                             '\n'.join(not_imported) + '\n')
1467                    not_imported = []
1468                if len(imported) > 0:
1469                    open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
1470                             '\n'.join(imported) + '\n')
1471                    imported = []
1472                em = '%d transactions committed\n' % (tr_count)
1473                regs = []
1474                logger.info(em)
1475                tr_count = 0
1476        if len(imported) > 0:
1477            open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
1478                                                '\n'.join(imported))
1479        if len(not_imported) > 0:
1480            open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1481                                                '\n'.join(not_imported))
1482        em = "Imported: %d, not imported: %d of total %d" % (total_imported,total_not_imported,total)
1483        return em
1484    ###)
1485
1486    security.declareProtected(ModifyPortalContent,"moveImagesToFS")###(
1487    def moveImagesToFS(self,student_id="O738726"):
1488        "move the images to the filesystem"
1489        images_dir = os.path.join("%s/images" % i_home,student_id)
1490        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1491        stool = getToolByName(self, 'portal_schemas')
1492        schemas = ['student_application',
1493                   'student_clearance',
1494                   ]
1495        created = False
1496        for schema_id in schemas:
1497            schema = stool._getOb(schema_id)
1498            object = getattr(student_folder,schema_id[len('student_'):],None)
1499            if object is None:
1500                continue
1501            doc = object.getContent()
1502            for key in schema.keys():
1503                if schema[key].meta_type != "CPS Image Field":
1504                    continue
1505                #import pdb;pdb.set_trace()
1506                image = getattr(doc,key,None)
1507                if not image or not hasattr(image,"data"):
1508                    continue
1509                if not created:
1510                    if not os.path.exists(images_dir):
1511                        os.mkdir(images_dir)
1512                    created = True
1513                filename = os.path.join(images_dir,"%(key)s_%(student_id)s.jpg" % vars())
1514                open(filename,"wb").write(str(image.data))
1515
1516    security.declareProtected(ModifyPortalContent,"movePassportToFS")###(
1517    def movePassportToFS(self,student_id="O738726"):
1518        "move the passports to the filesystem"
1519        images_dir = os.path.join("%s" % i_home,'passports')
1520        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1521        stool = getToolByName(self, 'portal_schemas')
1522        schemas = ['student_application',
1523                   #'student_clearance',
1524                   ]
1525        created = False
1526        for schema_id in schemas:
1527            schema = stool._getOb(schema_id)
1528            object = getattr(student_folder,schema_id[len('student_'):],None)
1529            if object is None:
1530                continue
1531            doc = object.getContent()
1532            for key in schema.keys():
1533                if schema[key].meta_type != "CPS Image Field":
1534                    continue
1535                #import pdb;pdb.set_trace()
1536                image = getattr(doc,key)
1537                if not hasattr(image,"data"):
1538                    continue
1539                if not created:
1540                    if not os.path.exists(images_dir):
1541                        os.mkdir(images_dir)
1542                    created = True
1543                filename = os.path.join(images_dir,"%(student_id)s.jpg" % vars())
1544                open(filename,"wb").write(str(image.data))
1545
1546InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.