source: WAeUP_SRP/base/WAeUPTool.py @ 2363

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

new function picturesExist in waeup_tool used in clearance_edit

  • Property svn:keywords set to Id
File size: 63.1 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 2363 2007-10-15 12:04:52Z 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('showFsPicture') ###(
705    def showFsPicture(self,path):
706        """return a picture from the filesystem"""
707        picture_path = os.path.join(i_home,path)
708        response = self.REQUEST.RESPONSE
709        #import pdb;pdb.set_trace()
710        registry = getToolByName(self, 'mimetypes_registry')
711        mimetype = str(registry.lookupExtension(path.lower()) or
712                    registry.lookupExtension('file.bin'))
713        if os.path.exists(picture_path):
714            response.setHeader('Content-type',mimetype)
715            return open(picture_path).read()
716        picture_path = os.path.join(i_home,'import',path)
717        if os.path.exists(picture_path):
718            return open(picture_path).read()
719    ###)
720
721    security.declareProtected(ModifyPortalContent,'deleteAllCourses') ###(
722    def deleteAllCourses(self,department="All"):
723        ''' delete the courses'''
724        pm = self.portal_membership
725        member = pm.getAuthenticatedMember()
726
727        if str(member) not in ("henrik","joachim"):
728            return "not possible"
729        if department == "All":
730            res = self.portal_catalog({'meta_type': 'Department'})
731        if len(res) < 1:
732            return "No Departments found"
733
734        deleted = []
735        for dep in res:
736            cf = dep.getObject().courses
737            if cf:
738                cf.manage_delObjects(ids=cf.objectIds())
739                deleted.append("deleted Courses in %s" % dep.getId)
740        return "\r".join(deleted)
741    ###)
742
743    security.declareProtected(ModifyPortalContent,'getLogfileLines') ###(
744    def getLogfileLines(self,filename="event.log",numlines=20):
745        """Get last NUMLINES lines of logfile FILENAME.
746
747        Return last lines' of a file in the instances logfile directory as
748        a list. The number of returned lines equals `numlines' or less. If
749        less than `numlines' lines are available, the whole file ist
750        returned. If the file can not be opened or some other error
751        occurs, empty list is returend.
752        """
753        result = []
754        lines_hit = 0
755
756        # We only handle files in instances' log directory...
757        logpath = os.path.join(i_home, "log")
758        filename = str(os.path.abspath( os.path.join( logpath, filename )))
759        if not filename.startswith( logpath ):
760            # Attempt to access file outside log-dir...
761            return []
762
763        try:
764            fd = file( filename, "rb" )
765        except IOError:
766            return []
767        if not fd:
768            return []
769
770        if os.linesep == None:
771            linesep = '\n'
772        else:
773            linesep = os.linesep
774
775        # Try to find 'numlines' times a lineseparator, searching from end
776        # and moving to the beginning of file...
777        fd.seek( 0, 2) # Move to end of file...
778        while lines_hit < numlines:
779            if fd.read(1) == linesep[-1]: # This moves filedescriptor
780                                          # one step forward...
781                lines_hit += 1
782            try:
783                fd.seek( -2, 1) # Go two bytes back from current pos...
784            except IOError:
785                # We cannot go back two bytes. Maybe the file is too small...
786                break
787        fd.seek(2,1)
788
789        # Read all lines from current position...
790        result = fd.readlines()
791        # Remove line endings...
792        result = [x.strip() for x in result]
793        fd.close()
794        return result
795    ###)
796
797    security.declareProtected(ModifyPortalContent,"getCallbacksFromLog")###(
798    def getCallbacksFromLog(self,filename):
799        """fix Online Payment Transactions from Z2.log entries"""
800        import transaction
801        import random
802        from cgi import parse_qs
803        from urlparse import urlparse
804        #from pdb import set_trace
805        wftool = self.portal_workflow
806        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
807        students_folder = self.portal_url.getPortalObject().campus.students
808        s = r'(?P<client_ip>\S+) - (?P<member_id>\S+) \['
809        s += r'(?P<date>.*)\] "(?P<get>.*)" (?P<codes>\d+ \d+) "'
810        s += r'(?P<intersw>.*)" "(?P<agent>.*)"'
811        data = re.compile(s)
812        start = True
813        tr_count = 1
814        total = 0
815        #name = 'pume_results'
816        #name = 'epaymentsuccessful_z2log2'
817        name = filename
818        no_import = []
819        imported = []
820        logger = logging.getLogger('WAeUPTool.getFailedTransactions')
821        try:
822            transactions = open("%s/import/%s" % (i_home,name),"rb").readlines()
823        except:
824            logger.error('Error reading %s' % name)
825            return
826        tas = []
827        for line in transactions:
828            dict = {}
829            items = data.search(line)
830            dict['idict'] = idict = items.groupdict()
831            #print idict
832            #from pdb import set_trace;set_trace()
833            urlparsed = urlparse(idict['get'][4:])
834            #print urlparsed
835            path = urlparsed[2].split('/')
836            dict['student_id'] = student_id = path[8]
837            dict['payment_id'] = payment_id = path[10]
838            dict['qs_dict'] = qs_dict = parse_qs(urlparsed[4])
839            tas.append(dict)
840            tr_count += 1
841        return tas
842    ###)
843
844    security.declareProtected(ModifyPortalContent,"importOnlinePaymentTransactions")###(
845    def importOnlinePaymentTransactions(self):
846        """load Online Payment Transactions from CSV values"""
847        import transaction
848        import random
849        #from pdb import set_trace
850        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
851        opt = self.online_payments_import
852        students_folder = self.portal_url.getPortalObject().campus.students
853        start = True
854        tr_count = 1
855        total = 0
856        #name = 'pume_results'
857        name = 'OnlineTransactions'
858        no_import = []
859        imported = []
860        logger = logging.getLogger('WAeUPTool.importOnlinePaymentTransactions')
861        try:
862            transactions = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
863        except:
864            logger.error('Error reading %s.csv' % name)
865            return
866        for pay_transaction in transactions:
867            if start:
868                start = False
869                logger.info('Start loading from %s.csv' % name)
870                s = ','.join(['"%s"' % fn for fn in pay_transaction.keys()])
871                no_import.append('%s,"Error"' % s)
872                format = ','.join(['"%%(%s)s"' % fn for fn in pay_transaction.keys()])
873                format_error = format + ',"%(Error)s"'
874            data = {}
875
876            # format of the first file sent by Tayo
877            #data['datetime'] = date = DateTime.DateTime(pay_transaction['Date'])
878            #data['student_id'] = student_id = pay_transaction['Payer ID']
879            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
880            #data['response_code'] = response_code = pay_transaction['Resp Code']
881            #data['amount'] = amount = pay_transaction['Amount']
882
883            # format of the second file sent by Tayo
884            #data['datetime'] = date = 0
885            #data['student_id'] = student_id = pay_transaction['Payer ID']
886            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
887            #data['response_code'] = response_code = '00'
888            #data['amount'] = amount = pay_transaction['Amount']
889
890            # format of the third file sent by Kehinde
891            data['datetime'] = date = 0
892            data['student_id'] = student_id = pay_transaction['customer_id']
893            data['order_id'] = order_id = pay_transaction['merchant_reference']
894            data['response_code'] = response_code = '00'
895            data['amount'] = amount = pay_transaction['Amount']
896
897            dup = False
898            if response_code == "12":
899                continue
900            try:
901                opt.addRecord(**data)
902            except ValueError:
903                dup = True
904            #from pdb import set_trace;set_trace()
905            if dup:
906                if response_code == "00":
907                    try:
908                        opt.modifyRecord(**data)
909                    except:
910                        logger.info("duplicate uid, order_id %(order_id)s, student_id %(student_id)s, response_code %(response_code)s" % data)
911                        continue
912                else:
913                    pay_transaction['Error'] = "Duplicate order_id"
914                    no_import.append( format_error % pay_transaction)
915                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
916                    continue
917            tr_count += 1
918            if tr_count > 1000:
919                if len(no_import) > 0:
920                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
921                             '\n'.join(no_import) + '\n')
922                    no_import = []
923                em = '%d transactions committed\n' % (tr_count)
924                transaction.commit()
925                regs = []
926                logger.info(em)
927                total += tr_count
928                tr_count = 0
929        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
930                                                '\n'.join(no_import))
931        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
932    ###)
933
934    security.declareProtected(ModifyPortalContent,'mass_create_faculty') ###(
935    def mass_create_faculty(self,mapping):
936        "create a faculty"
937        logger = logging.getLogger('WAeUPTool.mass_create_faculty')
938        academics_folder = self.portal_url.getPortalObject().campus.academics
939        fid = mapping['code']
940        if getattr(academics_folder,fid,None) is not None:
941            return '', "Faculty with ID: %s exists" % fid
942        logger.info('Creating Faculty %(code)s, %(title)s' % mapping)
943        try:
944            academics_folder.invokeFactory('Faculty', fid)
945        except BadRequest,E:
946            return '', "%s" % E
947        f = getattr(academics_folder,fid,None)
948        f.getContent().edit(mapping=mapping)
949        return fid,''
950    ###)
951
952    security.declareProtected(ModifyPortalContent,'mass_edit_faculty') ###(
953    def mass_edit_faculty(self,mapping):
954        "edit a faculty"
955        logger = logging.getLogger('WAeUPTool.mass_edit_faculty')
956        academics_folder = self.portal_url.getPortalObject().campus.academics
957        fid = mapping['code']
958        f = getattr(academics_folder,fid,None)
959        if f is None:
960            return '', "Faculty with ID: %s does not exist" % fid
961        logger.info('Editing Faculty %(code)s, %(title)s' % mapping)
962        f.getContent().edit(mapping=mapping)
963        return fid,''
964    ###)
965
966    security.declareProtected(ModifyPortalContent,'mass_create_department') ###(
967    def mass_create_department(self,mapping):
968        "create a department in the correct faculty"
969        logger = logging.getLogger('WAeUPTool.mass_create_department')
970        fid = mapping['faculty_code']
971        if getattr(self,'_v_faculties',None) is None:
972            res = self.portal_catalog(portal_type = "Faculty")
973            self._v_faculties = {}
974            for f in res:
975                self._v_faculties[f.getId] = f.getObject()
976        f = self._v_faculties.get(fid,None)
977        if f is None:
978            return '', "No Faculty with ID: %s" % fid
979        else:
980            did = mapping.get('code')
981            d = getattr(f,did,None)
982            if d is None or d.portal_type == "Faculty":
983                logger.info('Creating Department %(code)s, %(title)s' % mapping)
984                try:
985                    f.invokeFactory('Department', did)
986                except BadRequest,E:
987                    return '', "%s" % E
988                d = getattr(f,did)
989                d.invokeFactory('CoursesFolder','courses')
990                courses = getattr(d,'courses')
991                dict = {'Title': 'Courses'}
992                courses.getContent().edit(mapping=dict)
993                d.invokeFactory('CertificatesFolder','certificates')
994                certificates = getattr(d,'certificates')
995                dict = {'Title': 'Certificates'}
996                certificates.getContent().edit(mapping=dict)
997            d.getContent().edit(mapping=mapping)
998        return did,''
999    ###)
1000
1001    security.declareProtected(ModifyPortalContent,'mass_edit_department') ###(
1002    def mass_edit_department(self,mapping):
1003        "create a department in the correct faculty"
1004        logger = logging.getLogger('WAeUPTool.mass_create_department')
1005        academics_folder = self.portal_url.getPortalObject().campus.academics
1006        fid = mapping['faculty_code']
1007        did = mapping.get('code')
1008        try:
1009            d = getattr(getattr(academics_folder,fid),did,None)
1010        except KeyError:
1011            return '', "Department %s or Faculty %s wrong" % (did,fid)
1012        else:
1013            if d is None or d.portal_type == "Faculty":
1014                logger.info('Editing Department %(code)s, %(title)s' % mapping)
1015            d.getContent().edit(mapping=mapping)
1016        return did,''
1017    ###)
1018
1019    security.declareProtected(ModifyPortalContent,'mass_create_course') ###(
1020    def mass_create_course(self,mapping):
1021        #import pdb;pdb.set_trace()
1022        if getattr(self,'_v_course_list',None) is None:
1023            self._v_course_list = []
1024        if getattr(self,'_v_departments',None) is None:
1025            res = self.portal_catalog(portal_type = "Department")
1026            self._v_department_courses = {}
1027            for d in res:
1028                self._v_department_courses[d.getId] = getattr(d.getObject(),"courses",None)
1029        did = mapping['department_code']
1030        d = self._v_department_courses.get(did,None)
1031        if d is None:
1032            return '', "No Department with ID: %s" % did
1033        course_id = mapping.get('code')
1034        if course_id in self._v_course_list:
1035            return '', "Duplicate Course ID: %s" % did
1036        c = getattr(d,course_id,None)
1037        if c is not None:
1038            return '', "Duplicate Course ID: %s" % did
1039        try:
1040            d.invokeFactory('Course', course_id)
1041        except BadRequest,E:
1042            return '', "%s" % E
1043        self._v_course_list.append(course_id)
1044        c = getattr(d,course_id)
1045        c.getContent().edit(mapping=mapping)
1046        return course_id,''
1047    ###)
1048
1049    security.declareProtected(ModifyPortalContent,'mass_edit_course') ###(
1050    def mass_edit_course(self,mapping):
1051        #import pdb;pdb.set_trace()
1052        course_id = mapping.get('code')
1053        res = self.portal_catalog(id=course_id)
1054        if not res:
1055            return '', "No Course with ID: %s" % course_id
1056        c = res[0].getObject()
1057        c.getContent().edit(mapping=mapping)
1058        return course_id,''
1059    ###)
1060
1061    security.declareProtected(ModifyPortalContent,'mass_create_certificate') ###(
1062    def mass_create_certificate(self,mapping):
1063        if getattr(self,'_v_certificate_list',None) is None:
1064            self._v_certificate_list = []
1065        if getattr(self,'_v_department_certificates',None) is None:
1066            res = self.portal_catalog(portal_type = "Department")
1067            self._v_department_certificates = {}
1068            for d in res:
1069                self._v_department_certificates[d.getId] = getattr(d.getObject(),"certificates",None)
1070        did = mapping['department_code']
1071        d = self._v_department_certificates.get(did,None)
1072        if d is None:
1073            return '', "No Department with ID: %s" % did
1074        certificate_id = mapping.get('code')
1075        if certificate_id in self._v_certificate_list:
1076            return '', "Duplicate Certificate ID: %s" % did
1077        c = getattr(d,certificate_id,None)
1078        if c is not None:
1079            return '', "Duplicate Certificate ID: %s" % did
1080        try:
1081            d.invokeFactory('Certificate', certificate_id)
1082        except BadRequest,E:
1083            return '', "%s" % E
1084        self._v_certificate_list.append(certificate_id)
1085        c = getattr(d,certificate_id)
1086        c.getContent().edit(mapping=mapping)
1087        return certificate_id,''
1088    ###)
1089
1090    security.declareProtected(ModifyPortalContent,'mass_edit_certificate') ###(
1091    def mass_edit_certificate(self,mapping):
1092        #import pdb;pdb.set_trace()
1093        certificate_id = mapping.get('code')
1094        res = self.portal_catalog(id=certificate_id)
1095        if not res:
1096            return '', "No Certificate with ID: %s" % did
1097        c = res[0].getObject()
1098        c.getContent().edit(mapping=mapping)
1099        return certificate_id,''
1100    ###)
1101
1102    security.declareProtected(ModifyPortalContent,'mass_create_certificate_course') ###(
1103    def mass_create_certificate_course(self,mapping):
1104        if getattr(self,'_v_courses',None) is None:
1105            res = self.courses_catalog()
1106            self._v_courses= [course.code for course in res]
1107        if getattr(self,'_v_ceritficates',None) is None:
1108            res = self.portal_catalog(portal_type = "Certificate")
1109            self._v_certificates = {}
1110            for cert in res:
1111                self._v_certificates[cert.getId] = cert.getObject()
1112        certificate_course_id = mapping.get('code')
1113        if certificate_course_id not in self._v_courses:
1114            return '', "No Course with ID: %s" % certificate_course_id
1115        cert_id = mapping['certificate_code']
1116        cert = self._v_certificates.get(cert_id,None)
1117        if cert is None:
1118            return '', "No Certificate with ID: %s" % cert_id
1119        level_id = mapping.get('level')
1120        level = getattr(cert,level_id,None)
1121        if level is None:
1122            cert.invokeFactory('StudyLevel', level_id)
1123            level = getattr(cert,level_id,None)
1124        elif hasattr(level,certificate_course_id):
1125            return '', "Duplicate CertificateCourse ID: %s in %s/ %s" %\
1126            (certificate_course_id,cert_id,level_id)
1127        level.invokeFactory('CertificateCourse', certificate_course_id)
1128        c = getattr(level,certificate_course_id)
1129        c.getContent().edit(mapping=mapping)
1130        return certificate_course_id,''
1131    ###)
1132
1133    field2types_student = {   ###(
1134                      'StudentApplication':
1135                          {'id': 'application',
1136                           'title': 'Application Data',
1137                           'wf_transition_return': 'close',
1138                           'wf_transition_admit': 'remain',
1139                           'fields':
1140                             ('jamb_reg_no',
1141                              'entry_mode',
1142                              'entry_session',
1143                              'jamb_score',
1144                              'app_email',
1145                              'jamb_age',
1146                              #'jamb_state',
1147                              #'jamb_lga',
1148                              )
1149                              },
1150                      #'StudentPume':
1151                      #    {'id': 'pume',
1152                      #     'title': 'Pume Data',
1153                      #     'wf_transition_return': 'close',
1154                      #     'wf_transition_admit': 'close',
1155                      #     'fields':
1156                      #       ('pume_score',
1157                      #        )
1158                      #        },
1159                      'StudentClearance':
1160                          {'id': 'clearance',
1161                           'title': 'Clearance/Eligibility Record',
1162                           'wf_transition_return': 'close',
1163                           'wf_transition_admit': 'remain',
1164                           'fields':
1165                             ('matric_no',
1166                              'nationality',
1167                              'lga',
1168                              'birthday',
1169                              )
1170                              },
1171                         'StudentPersonal':
1172                          {'id': 'personal',
1173                           'title': 'Personal Data',
1174                           'wf_transition_return': 'open',
1175                           'wf_transition_admit': 'remain',
1176                           'fields':
1177                             ('firstname',
1178                              'middlename',
1179                              'lastname',
1180                              'sex',
1181                              'email',
1182                              'phone',
1183                              'perm_address',
1184                              )
1185                              },
1186                         'StudentStudyCourse':
1187                          {'id': 'study_course',
1188                           'title': 'Study Course',
1189                           'wf_transition_return': 'open',
1190                           'wf_transition_admit': 'remain',
1191                           'fields':
1192                             ('study_course',
1193                              'current_level',
1194                              'current_session',
1195                              'current_mode',
1196                              'current_verdict',
1197                              )
1198                              },
1199
1200                         'PaymentsFolder':
1201                          {'id': 'payments',
1202                           'title': 'Payments',
1203                           'wf_transition_return': 'open',
1204                           'wf_transition_admit': 'open',
1205                           'fields':
1206                             ()
1207                              },
1208                         }
1209    ###)
1210
1211    security.declareProtected(ModifyPortalContent,'mass_create_student') ###(
1212    def mass_create_student(self,mapping):
1213        "create a students record due import"
1214        logger = logging.getLogger('WAeUPTool.mass_create_student')
1215        students_folder = self.portal_url.getPortalObject().campus.students
1216        jamb_reg_no = mapping.get('jamb_reg_no',None)
1217        if jamb_reg_no:
1218            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1219            if res:
1220                return '',"jamb_reg_no exists"
1221        matric_no = mapping.get('matric_no',None)
1222        if matric_no:
1223            res = self.students_catalog(matric_no = matric_no)
1224            if res:
1225                return '',"matric_no exists"
1226        sid = self.waeup_tool.generateStudentId('?')
1227        students_folder.invokeFactory('Student', sid)
1228        student_obj = getattr(students_folder,sid)
1229        f2t = self.field2types_student
1230        d = {}
1231        d['jamb_sex']  = 'M'
1232        if mapping.get('sex'):
1233            d['jamb_sex']  = 'F'
1234        transition = mapping.get('reg_transition','admit')
1235        if transition not in ('admit','return'):
1236            return '',"no valid transition provided"
1237        for pt in f2t.keys():
1238            student_obj.invokeFactory(pt,f2t[pt]['id'])
1239            sub_obj = getattr(student_obj,f2t[pt]['id'])
1240            sub_doc = sub_obj.getContent()
1241            d['Title'] = f2t[pt]['title']
1242            for field in f2t[pt]['fields']:
1243                d[field] = mapping.get(field,'')
1244            if pt == "StudyCourse":
1245                for von,zu in (('entry_mode','current_mode'),
1246                               ('entry_session','current_session')):
1247                    if mapping.get(zu,None) is None and mapping.get(von,None) is not None:
1248                        d[zu] = mapping[von]
1249            sub_doc.edit(mapping = d)
1250
1251            #import pdb;pdb.set_trace()
1252            new_state = f2t[pt]['wf_transition_%(transition)s' % vars()]
1253            if new_state != "remain":
1254                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1255        self.portal_workflow.doActionFor(student_obj,transition)
1256        student_obj.manage_setLocalRoles(sid, ['Owner',])
1257        return sid,''
1258    ###)
1259
1260    security.declareProtected(ModifyPortalContent,'mass_edit_student') ###(
1261    def mass_edit_student(self,mapping):
1262        "edit a students record due import"
1263        logger = logging.getLogger('WAeUPTool.mass_edit_student')
1264        students_folder = self.portal_url.getPortalObject().campus.students
1265        sid = mapping.get('id',None)
1266        jamb_reg_no = mapping.get('jamb_reg_no',None)
1267        matric_no = mapping.get('matric_no',None)
1268        editable_keys = mapping.keys()
1269        if sid:
1270            res = self.students_catalog(id = sid)
1271            if not res:
1272                return '',"no student with id %s" % sid
1273            if matric_no and res[0].matric_no and\
1274              matric_no != res[0].matric_no:
1275                logger.info("%s, old matric_no %s overwritten with %s" % (res[0].id,res[0].matric_no,matric_no))
1276            if jamb_reg_no and res[0].jamb_reg_no and\
1277              jamb_reg_no != res[0].jamb_reg_no:
1278                logger.info("%s, old reg_no %s overwritten with %s" % (res[0].id,res[0].jamb_reg_no,jamb_reg_no))
1279        elif jamb_reg_no:
1280            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1281            if not res:
1282                return '',"no student with jamb_reg_no %s" % jamb_reg_no
1283            editable_keys.remove('jamb_reg_no')
1284        elif matric_no:
1285            res = self.students_catalog(matric_no = matric_no)
1286            if not res:
1287                return '',"no student with matric_no %s" % matric_no
1288            editable_keys.remove('matric_no')
1289
1290        ## included only to change wf state from admitted to returning
1291        #if res[0].review_state not in ('admitted','objection_raised'):
1292        #    return '%s' % res[0].id ,"student is not in state admitted or objection_raised"
1293        ## end inclusion
1294
1295        sid = res[0].id
1296        student_obj = getattr(students_folder,sid)
1297        f2t = self.field2types_student
1298        d = {}
1299        #import pdb;pdb.set_trace()
1300        any_change = False
1301        for pt in f2t.keys():
1302            if pt == "student_application":
1303                d['jamb_sex']  = 'M'
1304                if mapping.get('sex'):
1305                    d['jamb_sex']  = 'F'
1306            intersect = set(f2t[pt]['fields']).intersection(set(editable_keys))
1307            if intersect:
1308                sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1309                if sub_obj is None:
1310                    try:
1311                        student_obj.invokeFactory(pt,f2t[pt]['id'])
1312                    except:
1313                        continue
1314                    sub_obj = getattr(student_obj,f2t[pt]['id'])
1315                    d['Title'] = f2t[pt]['title']
1316                sub_doc = sub_obj.getContent()
1317                for field in intersect:
1318                    changed = False
1319                    if getattr(sub_doc,field) != mapping.get(field,''):
1320                        any_change = True
1321                        changed = True
1322                        d[field] = mapping.get(field,'')
1323                    if changed:
1324                        sub_doc.edit(mapping = d)
1325
1326
1327        ## included only to change wf state from admitted to returning
1328        #    if res[0].review_state in ('admitted','objection_raised'):
1329        #        new_state = f2t[pt]['wf_transition_return']
1330        #        sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1331        #        if sub_obj and new_state != "remain":
1332        #            try:
1333        #                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1334        #            except:
1335        #                #logger.info('%s, wf transition %s of %s failed' % (sid,new_state,sub_obj.id))
1336        #                pass
1337        #if res[0].review_state in ('admitted','objection_raised'):
1338        #    wfaction = 'return'
1339        #    try:
1340        #        self.portal_workflow.doActionFor(student_obj,wfaction)
1341        #        logger.info('%s, wf state changed' % sid)
1342        #        any_change = True
1343        #    except:
1344        #        logger.info('%s, wf transition failed, old state = %s' % (sid,res[0].review_state))
1345        #        pass
1346        ## end inclusion
1347
1348
1349        if any_change:
1350            return sid,''
1351        else:
1352            return sid,'not modified'
1353    ###)
1354
1355    security.declareProtected(ModifyPortalContent,"importData")###(
1356    def importData(self,filename,name,edit=False,bypass_queue_catalog=False):
1357        """load data from CSV values"""
1358        import transaction
1359        import random
1360
1361        pm = self.portal_membership
1362        member = pm.getAuthenticatedMember()
1363
1364        logger = logging.getLogger('WAeUPTool.importData')
1365        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1366        students_folder = self.portal_url.getPortalObject().campus.students
1367        start = True
1368        tr_count = 1
1369        total_imported = 0
1370        total_not_imported = 0
1371        total = 0
1372        iname = "import_%s" % name
1373        stool = getToolByName(self, 'portal_schemas')
1374        ltool = getToolByName(self, 'portal_layouts')
1375        schema = stool._getOb(iname)
1376        if schema is None:
1377            em = 'No such schema %s' % iname
1378            logger.error('No such schema %s' % iname)
1379            return em
1380        layout = ltool._getOb(iname)
1381        if layout is None:
1382            em = 'No such layout %s' % iname
1383            logger.error(em)
1384            return em
1385        validators = {}
1386        for widget in layout.keys():
1387            validators[widget] = layout[widget].validate
1388        #import pdb;pdb.set_trace()
1389        mode = "create"
1390        if edit:
1391            mode = "edit"
1392        importer_name = "mass_%(mode)s_%(name)s" % vars()
1393        importer = getattr(self, '%s' % importer_name,None)
1394        if importer is None:
1395            em = 'No importer function %s' % importer_name
1396            logger.error(em)
1397            return em
1398        not_imported = []
1399        imported = []
1400        try:
1401            items = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
1402        except:
1403            em = 'Error reading %s.csv' % filename
1404            logger.error(em)
1405            return em
1406        for item in items:
1407            if start:
1408                start = False
1409                adapters = [MappingStorageAdapter(schema, item)]
1410                logger.info('%s starts import from %s.csv in %s mode with schema and layout %s' % (member,filename,mode,iname))
1411                attrs = csv.reader(open("%s/import/%s.csv" % (i_home,filename),"rb")).next()
1412                import_keys = [k for k in attrs if not k.startswith('ignore')]
1413                diff2schema = set(import_keys).difference(set(schema.keys()))
1414                diff2layout = set(import_keys).difference(set(layout.keys()))
1415                if diff2schema:
1416                    em = 'not ignorable key(s): "%s" found in heading' % ", ".join(diff2schema)
1417                    return em
1418                s = ','.join(['"%s"' % fn for fn in import_keys])
1419                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(s + ',"Error"'+ '\n')
1420                s = '"id",' + s
1421                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
1422                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
1423                format_error = format + ',"%(Error)s"'
1424                format = '"%(id)s",'+ format
1425
1426            dm = DataModel(item, adapters,context=self)
1427            ds = DataStructure(data=item,datamodel=dm)
1428            error_string = ""
1429            for k in import_keys:
1430                #import pdb;pdb.set_trace()
1431                if not validators[k](ds,mode=mode):
1432                    error_string += " %s : %s" % (k,
1433                                                  self.translation_service(ds.getError(k),
1434                                                                           ds.getErrorMapping(k)))
1435            if not error_string:
1436                item.update(dm)
1437                item['id'],error = importer(item)
1438                if error:
1439                    error_string += error
1440            if error_string:
1441                item['Error'] = error_string
1442                not_imported.append(format_error % item)
1443                total_not_imported += 1
1444            else:
1445                em = format % item
1446                imported.append(em)
1447                logger.info("%(total_imported)d of %(total)d %(em)s" % vars())
1448                tr_count += 1
1449                total_imported += 1
1450            total += 1
1451            if total and not total % 100:
1452                transaction.commit()
1453                if len(not_imported) > 0:
1454                    open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1455                             '\n'.join(not_imported) + '\n')
1456                    not_imported = []
1457                if len(imported) > 0:
1458                    open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
1459                             '\n'.join(imported) + '\n')
1460                    imported = []
1461                em = '%d transactions committed\n' % (tr_count)
1462                regs = []
1463                logger.info(em)
1464                tr_count = 0
1465        if len(imported) > 0:
1466            open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
1467                                                '\n'.join(imported))
1468        if len(not_imported) > 0:
1469            open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1470                                                '\n'.join(not_imported))
1471        em = "Imported: %d, not imported: %d of total %d" % (total_imported,total_not_imported,total)
1472        return em
1473    ###)
1474
1475    security.declareProtected(ModifyPortalContent,"moveImagesToFS")###(
1476    def moveImagesToFS(self,student_id="O738726"):
1477        "move the images to the filesystem"
1478        images_dir = os.path.join("%s/images" % i_home,student_id)
1479        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1480        stool = getToolByName(self, 'portal_schemas')
1481        schemas = ['student_application',
1482                   'student_clearance',
1483                   ]
1484        created = False
1485        for schema_id in schemas:
1486            schema = stool._getOb(schema_id)
1487            object = getattr(student_folder,schema_id[len('student_'):],None)
1488            if object is None:
1489                continue
1490            doc = object.getContent()
1491            for key in schema.keys():
1492                if schema[key].meta_type != "CPS Image Field":
1493                    continue
1494                #import pdb;pdb.set_trace()
1495                image = getattr(doc,key,None)
1496                if not image or not hasattr(image,"data"):
1497                    continue
1498                if not created:
1499                    if not os.path.exists(images_dir):
1500                        os.mkdir(images_dir)
1501                    created = True
1502                filename = os.path.join(images_dir,"%(key)s_%(student_id)s.jpg" % vars())
1503                open(filename,"wb").write(str(image.data))
1504
1505    security.declareProtected(ModifyPortalContent,"movePassportToFS")###(
1506    def movePassportToFS(self,student_id="O738726"):
1507        "move the passports to the filesystem"
1508        images_dir = os.path.join("%s" % i_home,'passports')
1509        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1510        stool = getToolByName(self, 'portal_schemas')
1511        schemas = ['student_application',
1512                   #'student_clearance',
1513                   ]
1514        created = False
1515        for schema_id in schemas:
1516            schema = stool._getOb(schema_id)
1517            object = getattr(student_folder,schema_id[len('student_'):],None)
1518            if object is None:
1519                continue
1520            doc = object.getContent()
1521            for key in schema.keys():
1522                if schema[key].meta_type != "CPS Image Field":
1523                    continue
1524                #import pdb;pdb.set_trace()
1525                image = getattr(doc,key)
1526                if not hasattr(image,"data"):
1527                    continue
1528                if not created:
1529                    if not os.path.exists(images_dir):
1530                        os.mkdir(images_dir)
1531                    created = True
1532                filename = os.path.join(images_dir,"%(student_id)s.jpg" % vars())
1533                open(filename,"wb").write(str(image.data))
1534
1535InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.