source: WAeUP_SRP/base/WAeUPTool.py @ 2669

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

forgot

  • Property svn:keywords set to Id
File size: 78.6 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 2666 2007-11-15 15:06:02Z 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
45import DateTime,time
46import logging
47import transaction
48import csv,re,os,sys
49from shutil import copy2
50from Products.AdvancedQuery import Eq, Between, Le,In
51
52p_home = package_home(globals())
53i_home = INSTANCE_HOME
54images_base = os.path.join(i_home,"images")
55
56
57def getObject(object,name):
58    if object.hasObject(name):
59        return getattr(object,name)
60    return None
61
62class WAeUPTool(UniqueObject, SimpleItem, ActionProviderBase):
63    """WAeUP tool"""
64
65    id = 'waeup_tool'
66    meta_type = 'WAeUP Tool'
67    _actions = ()
68    security = ClassSecurityInfo()
69    security.declareObjectProtected(View)
70    manage_options = ( ActionProviderBase.manage_options
71                     + SimpleItem.manage_options
72                     )
73
74    def rwrite(self,s): ###(
75        response = self.REQUEST.RESPONSE
76        response.setHeader('Content-type','text/html; charset=ISO-8859-15')
77        response.write("%s<br />\r\n" % s)
78    ###)
79
80    def sleep(self,secs): ###(
81        "sleep"
82        import time
83        time.sleep(secs)
84        return
85
86###)
87
88    security.declareProtected(ModifyPortalContent,'openLog') ###(
89    def openLog(self,name):
90        """open a log file"""
91        version = 1
92        path = "%s/log/%s_%d.log" % (i_home,name,version)
93        while os.path.exists(path):
94            version += 1
95            path = "%s/log/%s_%d.log" % (i_home,name,version)
96        log = open(path,"w")
97        return log
98    ###)
99
100    security.declareProtected(ModifyPortalContent,'bypassQueueCatalog') ###(
101    def bypassQueueCatalog(self,enable=True):
102        """bypass the QueueCatalog by setting all indexes to process imediate,
103        if enable is True (default) the old settings are restored
104        """
105
106    ###)
107
108    security.declareProtected(ModifyPortalContent,'measureOaT') ###(
109    def measureOaT(self,method="a",probe="1000",nr_pts="1"):
110        """measure Object access Time"""
111        import random
112        if hasattr(self,'portal_catalog_real'):
113            aq_portal = self.portal_catalog_real.evalAdvancedQuery
114        else:
115            aq_portal = self.portal_catalog.evalAdvancedQuery
116        nr_pts = int(nr_pts)
117        probe = int(probe)
118        intervall = probe/10
119        objects = ("application","clearance","personal")
120        portal_types = ("StudentApplication","StudentClearance","StudentPersonal")
121        #i = random.randrange(num_objects)
122        count = 0
123        found = 0
124        not_found = 0
125        t_found = 0
126        t_not_found = 0
127        time_found = time_not_found = 0.0
128        t_time_found = t_time_not_found = 0.0
129        accessed = []
130        t_min = 1000
131        t_max = 0
132        #import pdb;pdb.set_trace()
133        students = self.portal_catalog(portal_type="Student")
134        num_students = len(students)
135        if method == "d":
136            query = Eq('path','/uniben/campus/students') & In('portal_type',portal_types[:nr_pts])
137            res = aq_portal(query)
138            brains = {}
139            for r in res:
140                sid = r.relative_path.split('/')[-2]
141                if brains.has_key(sid):
142                    brains[sid][r.portal_type] = r
143                else:
144                    brains[sid] = {r.portal_type : r}
145            brains_list = brains.keys()
146            num_objects = len(brains_list)
147        else:
148            num_objects = num_students
149        print "="*40
150        print "method: %s probes: %d nr_pts: %d num_objects: %d" % (method,
151                                                                        probe,
152                                                                        nr_pts,
153                                                                        num_objects)
154        print "nr found/not time found/not min/max"
155        elapse = time.time()
156        i_elapse = time.time()
157        c_elapse = time.clock()
158        for c in range(1,probe + 1):
159            i = random.randrange(num_objects)
160            if method in ('a','b','c'):
161                student_brain = students[i]
162            elif method == "d":
163                #import pdb;pdb.set_trace()
164                student_brain = brains[brains_list[i]]
165            if method == "c":
166                query = Eq('path',student_brain.getPath()) & In('portal_type',portal_types[:nr_pts])
167                res = aq_portal(query)
168                this_portal_types = [r.portal_type for r in res]
169            for i in range(nr_pts):
170                oid = objects[i]
171                if method == "a":
172                    try:
173                        student_path = student_brain.getPath()
174                        path = "%s/%s" % (student_path,oid)
175                        doc = self.unrestrictedTraverse(path).getContent()
176                        found += 1
177                        i_time = time.time() - i_elapse
178                        time_found += i_time
179                    except:
180                        not_found += 1
181                        i_time = time.time() - i_elapse
182                        time_not_found += i_time
183                        pass
184                elif method == "b":
185                    try:
186                        student_object = student_brain.getObject()
187                        doc = getattr(student_object,oid).getContent()
188                        found += 1
189                        i_time = time.time() - i_elapse
190                        time_found += i_time
191                    except:
192                        i_time = time.time() - i_elapse
193                        time_not_found += i_time
194                        not_found += 1
195                        pass
196                elif method == "c":
197                    if portal_types[i] in this_portal_types:
198                        found += 1
199                        doc = res[this_portal_types.index(portal_types[i])].getObject().getContent()
200                        i_time = time.time() - i_elapse
201                        time_found += i_time
202                    else:
203                        not_found += 1
204                        i_time = time.time() - i_elapse
205                        time_not_found += i_time
206                elif method == "d":
207                    if student_brain.has_key(portal_types[i]):
208                        found += 1
209                        doc = student_brain[portal_types[i]].getObject().getContent()
210                        i_time = time.time() - i_elapse
211                        time_found += i_time
212                    else:
213                        not_found += 1
214                        i_time = time.time() - i_elapse
215                        time_not_found += i_time
216                i_elapse = time.time()
217            if c and (c % intervall == 0):
218                #i_time = time.time() - i_elapse
219                t_per = 0.0
220                if found:
221                    t_per = time_found/found
222                if t_per > t_max:
223                    t_max = t_per
224                if t_per > 0.0 and t_per < t_min:
225                    t_min = t_per
226                itf = 0.0
227                if found:
228                    itf = time_found/found
229                itnf = 0.0
230                if not_found :
231                    itnf = time_not_found / not_found
232                interval_time = time_found + time_not_found
233                s = "%(c)d: %(found)d/%(not_found)d " % vars()
234                s += "%(interval_time)6.2f %(itf)6.4f/%(itnf)6.4f " % vars()
235                s += "%(t_min)6.4f/%(t_max)6.4f" %  vars()
236                print s
237                t_found += found
238                t_not_found += not_found
239                t_time_found += time_found
240                t_time_not_found += time_not_found
241                time_found = time_not_found = 0.0
242                found = not_found = 0
243        # t_found += found
244        # t_not_found += not_found
245        elapse = time.time() - elapse
246        itf = 0.0
247        if t_found:
248            itf = t_time_found/t_found
249        itnf = 0.0
250        if t_not_found:
251            itnf = t_time_not_found / t_not_found
252        #c_elapse = time.clock() - c_elapse
253        s = "%(probe)d: %(t_found)d/%(t_not_found)d " % vars()
254        s += "%(elapse)6.2f %(itf)6.4f/%(itnf)6.4f " % vars()
255        s += "%(t_min)6.4f/%(t_max)6.4f" %  vars()
256        print "-"*40
257        print s
258        rel_found = float(t_found)/probe
259        rel_not_found = float(t_not_found)/probe
260        estimated_total_time = num_objects*(rel_found*itf + rel_not_found*itnf)
261        print estimated_total_time
262    ###)
263
264    security.declareProtected(ModifyPortalContent,'writeLog') ###(
265    def writeLog(self,logfile,s):
266        """write to the log file"""
267        logfile.write(s)
268
269###)
270
271    def generateStudentId(self,letter): ###(
272        import random
273        r = random
274        ##if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
275        if letter == '?':
276            letter= r.choice('ABCDEFGHKLMNPQRSTUVWXY')
277        sid = "%c%d" % (letter,r.randint(99999,1000000))
278        students = self.portal_url.getPortalObject().campus.students
279##        while hasattr(students, sid):
280##            sid = "%c%d" % (letter,r.randint(99999,1000000))
281        while self.students_catalog(id = sid):
282            sid = "%c%d" % (letter,r.randint(99999,1000000))
283        return sid
284    ###)
285
286    def generatePassword(self,s=None): ###(
287        import random
288        r = random
289        ##if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
290        if s is None:
291            s = 'abcdefghklmnpqrstuvwxy23456789'
292        pw = ''
293        while len(pw) < 6:
294            pw += r.choice(s)
295        return pw
296    ###)
297
298    security.declareProtected(ModifyPortalContent, 'dumpSchoolfeePayments') ###(
299    def dumpSchoolfeePayments(self):
300        "dump paid schoolfees"
301        mtool = self.portal_membership
302        member = mtool.getAuthenticatedMember()
303        logger = logging.getLogger('WAeUPTool.dumpSchoolfees')
304        aq_student = self.students_catalog.evalAdvancedQuery
305        query = In('review_state',('schoolfee_paid',
306                                   'courses_registered',
307                                   'courses_validated',
308                                   ))
309        res = aq_student(query)
310        #import pdb;pdb.set_trace()
311        l = []
312        logger.info("start for %d" % len(res))
313        count = 1
314        log_after = 100
315        for student in res:
316            if not count % log_after:
317                logger.info("processed %d total %d" % (log_after,count))
318            count += 1
319            fee_dict =self.getSchoolFee(student)
320            fulltime = student.mode.endswith('_ft')
321            d = {}
322            d['student_id'] = student.id
323            d['name'] = student.name
324            d['amount'] = fee_dict.get(new_returning)
325            l += d,
326        csv_name = self.dumpListToCSV(l,'payments')
327        logger.info('%s dumped payments to %s' % (member,export_file))
328    ###)
329
330    security.declarePublic('dumpListToCSV') ###(
331    def dumpListToCSV(self,l,filename,fields=None):
332        """dump a list of dicts to a CSV file"""
333        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
334        export_file = "%s/export/%s_%s.csv" % (i_home,filename,current,)
335        if fields is None:
336            fields = l[0].keys()
337        headline = ','.join(fields)
338        out = open(export_file,"wb")
339        out.write(headline +'\n')
340        out.close()
341        out = open(export_file,"a")
342        csv_writer = csv.DictWriter(out,fields,)
343        csv_writer.writerows(l)
344        return export_file
345    ###)
346
347    security.declareProtected(ManagePortal, 'listMembers') ###(
348    def listMembers(self):
349        "list all members"
350        mtool = self.portal_membership
351        member = mtool.getAuthenticatedMember()
352        logger = logging.getLogger('WAeUPTool.listMembers')
353        if str(member) not in ('admin','joachim'):
354            logger.info('%s tried to list members' % (member))
355            return None
356        members = self.portal_directories.members
357        all = members.listEntryIdsAndTitles()
358        l = []
359        for user_id,name in all:
360            d = {}
361            d['user_id'] = user_id
362            d['name'] = name
363            d['pw'] = getattr(getattr(members,user_id),'password')
364            d['email'] = getattr(getattr(members,user_id),'email')
365            d['groups'] = " ".join(getattr(getattr(members,user_id),'groups'))
366            d['roles'] = " ".join(getattr(getattr(members,user_id),'roles'))
367            l += d,
368        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
369        export_file = "%s/export/member_list_%s.csv" % (i_home,current,)
370        logger.info('%s dumped memberlist to %s' % (member,export_file))
371        fields = l[0].keys()
372        headline = ','.join(fields)
373        out = open(export_file,"wb")
374        out.write(headline +'\n')
375        out.close()
376        out = open(export_file,"a")
377        csv_writer = csv.DictWriter(out,fields,)
378        csv_writer.writerows(l)
379    ###)
380
381    security.declareProtected(ManagePortal, 'removeDeletedDocIds') ###(
382    def removeDeletedDocIds(self, max=1000):
383        """
384        remove deleted docids from repository commit after max
385        """
386        logger = logging.getLogger('WAeUPTool.removeDeletedDocIds')
387        repository = getToolByName(self, 'portal_repository')
388        pxtool = getToolByName(self, 'portal_proxies')
389        logger.info('start')
390        pxtool_infos = pxtool.getRevisionsUsed()
391        logger.info('found  %d used revisions ' % (len(pxtool_infos)))
392
393        nb_revs = 0
394        docids_d = {} # all docids
395        unused_docids_d = {} # all docids that are unused
396        ids_unused_revs_docids = [] # ids for revs of unused docids
397        unused_ids = [] # ids for unused revs
398        total = 0
399        idlist = repository.objectIds()
400        to_delete = 0
401        found = False
402        for id in idlist:
403            docid, rev = repository._splitId(id)
404            if docid is None:
405                logger.info("invalid doc_id %s" % docid)
406                continue
407            nb_revs += 1
408            if not pxtool_infos.has_key(docid):
409                found = True
410                to_delete += 1
411                unused_ids.append(id)
412            elif not pxtool_infos[docid].has_key(rev):
413                found = True
414                to_delete += 1
415                unused_ids.append(id)
416            if found and not to_delete % max:
417                found = False
418                #import pdb;pdb.set_trace()
419                repository.manage_delObjects(unused_ids)
420                transaction.commit()
421                logger.info('removed %d total %d unused docids ' % (max,to_delete))
422        else:
423            if unused_ids:
424                repository.manage_delObjects(unused_ids)
425                transaction.commit()
426        logger.info('finished removing %d unused docids ' % (to_delete))
427
428
429###)
430
431    security.declareProtected(View,'getCredential') ###(
432    def getCredential(self,student_id):
433        "return a student password"
434        student_entry = getattr(self.portal_directories.students,student_id,None)
435        if not self.isStaff():
436            mtool = self.portal_membership
437            member = mtool.getAuthenticatedMember()
438            logger = logging.getLogger('WAeUPTool.getCredential')
439            logger.info('%s tried to access password of %s' % (member,student_id))
440            return None
441        if student_entry is None:
442            return None
443        return getattr(student_entry,"password","not set")
444    ###)
445
446    security.declarePublic('checkPassword') ###(
447    def checkPassword(self,student_id,password):
448        "return a student password"
449        student_entry = getattr(self.portal_directories.students,student_id,None)
450        if student_entry is None:
451            return False
452        return getattr(student_entry,"password","not set") == password
453    ###)
454
455    security.declareProtected(ModifyPortalContent,'editPassword') ###(
456    def editPassword(self,student_id,password):
457        "edit a student password"
458        student_entry = getattr(self.portal_directories.students,student_id,None)
459        if student_entry is None:
460            return
461        setattr(student_entry,'password',password)
462    ###)
463
464    security.declareProtected(ModifyPortalContent,'doCommit') ###(
465    def doCommit(self,logger=None):
466        "commit some transactions"
467        transaction.commit()
468    ###)
469
470    security.declarePublic('loadStudentFoto') ###(
471    def loadStudentFoto(self,student,filename,folder):
472        "return a student passport picture"
473        #import pdb;pdb.set_trace()
474        picture ="%s/import/%s/%s" % (i_home,folder,filename)
475        student_id = student.getId()
476        images_dir = os.path.join("%s" % images_base,student_id)
477        if not os.path.exists(images_dir):
478            os.mkdir(images_dir)
479        image_name = os.path.join(images_dir,"passport_%(student_id)s.jpg" % vars())
480        for extension in ('.jpg','.JPG'):
481            fullname = "%(picture)s%(extension)s" % vars()
482            if os.path.exists(fullname):
483                copy2(fullname,image_name)
484                return "successfully copied passport picture"
485        return "passport picture not found: %s.jpg or .JPG" % picture
486    ###)
487
488    def old____loadStudentFoto(self,student,filename,folder): ###(
489        "return a student passport picture"
490        app = student.application
491        app_doc = app.getContent()
492        #clear = student.clearance
493        #clear_doc = clear.getContent()
494        #matric_no = clear_doc.matric_no.upper()
495        picture1 ="%s/import/%s/%s.jpg" % (i_home,folder,filename)
496        picture2 ="%s/import/%s/%s.JPG" % (i_home,folder,filename)
497        #import pdb;pdb.set_trace()
498        if os.path.exists(picture1):
499            file = open(picture1)
500        elif os.path.exists(picture2):
501            file = open(picture2)
502        else:
503            return "passport picture not found %s" % picture1
504        reopened = False
505        if self.portal_workflow.getInfoFor(app,'review_state',None) !='opened':
506            self.portal_workflow.doActionFor(app,'open')
507            reopened = True
508        outfile = file.read()
509        app_doc.manage_addFile('passport',
510                               file=outfile,
511                               title="%s.jpg" % filename)
512        if reopened:
513            self.portal_workflow.doActionFor(app,'close')
514        return "successfully loaded passport picture"
515    ###)
516
517    security.declareProtected(ModifyPortalContent,'createOne') ###(
518    def createOne(self,students_folder,student_brain,letter,commit=False):
519        sid = self.waeup_tool.generateStudentId(letter)
520        students_folder.invokeFactory('Student', sid)
521        student = getattr(students_folder,sid)
522        self.portal_workflow.doActionFor(student,'return')
523        student.manage_setLocalRoles(sid, ['Owner',])
524        matric_no = student_brain.matric_no
525        jamb_reg_no = student_brain.Entryregno
526        self.students_catalog.addRecord(id = sid,
527                                           matric_no = matric_no,
528                                           jamb_reg_no = jamb_reg_no,
529                                           sex = student_brain.Sex == "F",
530                                           name = "%s %s %s" % (student_brain.Firstname,
531                                                                student_brain.Middlename,
532                                                                student_brain.Lastname)
533                                        )
534        if commit:
535            transaction.commit()
536        return sid,jamb_reg_no
537    ###)
538
539    security.declareProtected(ModifyPortalContent,'addStudent') ###(
540    def addStudent(self,dict):
541        students_folder = self.portal_url.getPortalObject().campus.students
542        sid = self.waeup_tool.generateStudentId('?')
543        students_folder.invokeFactory('Student', sid)
544        student_obj = getattr(students_folder,sid)
545        f2t = self.student_field2types
546        #from pdb import set_trace; set_trace()
547        d = {}
548        #d['jamb_sex']  = 'M'
549        #if dict.get('sex'):
550        #    d['jamb_sex']  = 'F'
551
552        entry_session = dict.get('entry_session')
553        if entry_session == self.getSessionId()[0]:
554            wfaction = 'admit'
555            wft = 'wf_transition_admit'
556            password = None
557        else:
558            wfaction = 'return'
559            wft = 'wf_transition_return'
560            password = self.generatePassword()
561            self.makeStudentMember(sid,password)
562
563        for pt in f2t.keys():
564            student_obj.invokeFactory(pt,f2t[pt]['id'])
565            sub_obj = getattr(student_obj,f2t[pt]['id'])
566            sub_doc = sub_obj.getContent()
567            #self.portal_workflow.doActionFor(sub_obj,'open',dest_container=sub_obj)
568            d['Title'] = f2t[pt]['title']
569            for field in f2t[pt]['fields']:
570                d[field] = dict.get(field,'')
571            sub_doc.edit(mapping = d)
572            new_state = f2t[pt][wft]
573            if new_state != "remain":
574                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
575        self.portal_workflow.doActionFor(student_obj,wfaction)
576        student_obj.manage_setLocalRoles(sid, ['Owner',])
577        return sid,password
578    ###)
579
580    security.declarePublic('getCertificateBrain') ###(
581    def getCertificateBrain(self,cert_id):
582        "do it"
583        res = ZCatalog.searchResults(self.portal_catalog_real,
584                                {'portal_type':"Certificate",
585                                      'id': cert_id})
586        if res:
587            return res[0]
588        return None
589    ###)
590
591    security.declareProtected(ModifyPortalContent,'get_csv_filenames') ###(
592    def get_csv_filenames(self):
593        "do it"
594        files = [file for file in os.listdir("%s/import/" % (i_home))
595                 if file.endswith('.csv') and file.find('imported') == -1]
596        return files
597    ###)
598
599    security.declarePublic('findStudentByMatricelNo') ###(
600    def findStudentByMatricelNo(self,matric_no):
601        "do it"
602        res = ZCatalog.searchResults(self.portal_catalog_real,
603                                {'portal_type':"StudentClearance",
604                                 'SearchableText': matric_no})
605        if res:
606            return res[0]
607        return None
608    ###)
609
610    security.declarePublic('makeStudentMember') ###(
611    def makeStudentMember(self,sid,password='uNsEt'):
612        """make the student a member"""
613        membership = self.portal_membership
614        membership.addMember(sid,
615                             password ,
616                             roles=('Member',
617                                     'Student',
618                                     ),
619                             domains='',
620                             properties = {'memberareaCreationFlag': False,
621                                           'homeless': True},)
622        member = membership.getMemberById(sid)
623        self.portal_registration.afterAdd(member, sid, password, None)
624        #self.manage_setLocalRoles(sid, ['Owner',])
625    ###)
626
627    security.declareProtected(View,'makeStudentData') ###(
628    def makeStudentData(self,student_id,email=None,phone_nr=None):
629        "create Datastructure for a returning Student"
630        #import pdb;pdb.set_trace()
631        logger = logging.getLogger('WAeUPTool.makeStudentData')
632        students_folder = self.portal_url.getPortalObject().campus.students
633        #res = self.students_catalog(id=student_id)
634        #if res:
635        #    st = res[0]
636        #res = self.returning_import(matric_no = st.matric_no)
637        res = self.returning_import(id = student_id)
638        if res:
639            student = res[0]
640        else:
641            logger.info('Id %s not found in returning_import' % student_id)
642            return
643        logger.info('%s creates data structure' % student_id)
644        s_results = self.results_import(matric_no = student.matric_no)
645        if s_results:
646            lnr = self.getLevelFromResultsCosCode(s_results)
647            level = "%d00" % lnr
648            verdict,eligible = self.getVerdict(s_results[0].Verdict)
649            #if eligible:
650            #    level = "%d00" % (lnr + 1)
651        else:
652            logger.info('matric_no %s not found in results_import' % student.matric_no)
653            level = ''
654            verdict = ''
655        #student should not be allowed to perform this transition
656        #wftool = self.portal_workflow
657        #wftool.doActionFor(student,'return')
658        certcode_org = student.Coursemajorcode
659        certcode = makeCertificateCode(certcode_org)
660        certificate_brain = self.getCertificateBrain(certcode)
661        if not certificate_brain:
662            em = 'Certificate %s org-code %s not found\n' % (certcode, certcode_org)
663            logger.info(em)
664        matric_no = student.matric_no
665        sid = student_id
666        student_obj = getattr(students_folder,sid)
667        student_obj.invokeFactory('StudentApplication','application')
668        application = student_obj.application
669        self.portal_workflow.doActionFor(application,'open',dest_container=application)
670        da = {'Title': 'Application Data'}
671        student_obj.invokeFactory('StudentPersonal','personal')
672        da['jamb_reg_no'] = student.Entryregno
673        em = self.getEntryMode(student.Entryregno)
674        da['entry_mode'] = em
675        personal = student_obj.personal
676        self.portal_workflow.doActionFor(personal,'open',dest_container=personal)
677        dp = {'Title': 'Personal Data'}
678        student_obj.invokeFactory('StudentClearance','clearance')
679        clearance = student_obj.clearance
680        self.portal_workflow.doActionFor(clearance,'open',dest_container=clearance)
681        dc = {'Title': 'Clearance/Eligibility Record'}
682        dc['matric_no'] = matric_no
683        state = student.State
684        lga = student.LGA
685        if state and lga:
686            lga =  state + ' / ' + lga
687        else:
688            lga = "None"
689        da['jamb_lga'] = dc['lga'] = lga
690        da['app_email'] = dp['email'] = email
691        da['app_mobile'] = dp['phone'] = phone_nr
692        dp['firstname'] = student.Firstname
693        dp['middlename'] = student.Middlename
694        dp['lastname'] = student.Lastname
695        da['jamb_lastname'] = "%s %s %s" % (student.Firstname,student.Middlename,student.Lastname)
696        da['jamb_sex'] = student.Sex
697        dp['sex'] = student.Sex == 'F'
698        dp['perm_address'] = student.Permanent_Address
699        application.getContent().edit(mapping=da)
700        self.portal_workflow.doActionFor(application,'close',dest_container=application)
701        personal.getContent().edit(mapping=dp)
702        clearance.getContent().edit(mapping=dc)
703        self.portal_workflow.doActionFor(clearance,'close',dest_container=clearance)
704        #
705        # Study Course
706        #
707        student_obj.invokeFactory('StudentStudyCourse','study_course')
708        studycourse = student_obj.study_course
709        self.portal_workflow.doActionFor(studycourse,'open',dest_container=studycourse)
710        dsc = {}
711        dsc['study_course'] = certcode
712        dsc['current_level'] = level
713        dsc['current_verdict'] = verdict
714        dsc['current_mode'] = em
715        dsc['current_session'] = '05'
716        studycourse.getContent().edit(mapping=dsc)
717        #
718        # Level
719        #
720##        l = getattr(studycourse,level,None)
721##        if l is None:
722##            studycourse.invokeFactory('StudentStudyLevel', level)
723##            l = getattr(studycourse, level)
724##            self.portal_workflow.doActionFor(l,'open',dest_container=l)
725##            l.getContent().edit(mapping={'Title': "Level %s" % level})
726###)
727
728    security.declareProtected(ModifyPortalContent,'admitOneStudent') ###(
729    def admitOneStudent(self,brain,entry_session,pin_password):
730        "create Datastructure for an admitted Student"
731        #import pdb;pdb.set_trace()
732        students_folder = self.portal_url.getPortalObject().campus.students
733        logger = logging.getLogger('WAeUPTool.admitStudent')
734        if brain.status != "admitted":
735            logger.info('status of %s is %s' % (brain.reg_no,brain.status))
736            return
737        pin_parts = brain.pin.split('-')
738        if len(pin_parts) != 3:
739            logger.info('invalid pin %s for %s' % (brain.pin,brain.reg_no))
740            return
741        student_id = self.generateStudentId('?')
742        students_folder.invokeFactory('Student', student_id)
743        student_object = getattr(students_folder,student_id)
744        if pin_password:
745            password = pin_parts[2]
746            self.makeStudentMember(student_id,password = password)
747        student_object.manage_setLocalRoles(student_id, ['Owner',])
748        #logger.info("creating %s reg_no %s" % (student_id,brain.reg_no))
749        #
750        # application
751        #
752        student_object.invokeFactory('StudentApplication','application')
753        application = student_object.application
754        #self.portal_workflow.doActionFor(application,'open',dest_container=application)
755        da = {'Title': 'Application Data'}
756        da['jamb_reg_no'] = brain.reg_no
757
758        sex = 'M'
759        if brain.sex:
760            sex = 'F'
761        da['jamb_sex'] = sex
762        #da['app_ac_pin'] = brain.pin
763        #if brain.lga:
764        #    state_lga = brain.lga.split('_')
765        #    da['state_lga'] = state_lga[0]
766        #    da['jamb_lga'] = state_lga[-1]
767        da['state_lga'] = brain.jamb_lga
768        da['jamb_lga'] = brain.jamb_state
769        da['jamb_score'] = brain.aggregate
770        da['app_email'] = brain.email
771        da['app_mobile'] = brain.phone
772        if brain.entry_mode:
773            da['entry_mode'] = brain.entry_mode
774        elif brain.screening_type == 'pume':
775            da['entry_mode'] = 'ume_ft'
776        elif brain.screening_type == 'pde':
777            da['entry_mode'] = 'de_ft'
778        else:
779            da['entry_mode'] = brain.screening_type
780        da['entry_session'] = entry_session
781        da['jamb_lastname'] = brain.lastname
782        da['jamb_middlename'] = brain.middlenames   # different field names!
783        da['firstname'] = brain.firstname
784        da['screening_application_date'] = brain.application_date
785        da['date_of_birth'] = brain.date_of_birth
786        da['jamb_first_cos'] = brain.course1
787        da['jamb_second_cos'] = brain.course2
788        da['course3'] = brain.course3
789        da['screening_type'] = brain.screening_type
790        da['screening_score'] = brain.screening_score
791        da['screening_date'] = brain.screening_date
792        da['hq_type'] = brain.hq_type
793        da['hq_grade'] = brain.hq_grade
794        da['aos'] = brain.aos
795
796        application.getContent().edit(mapping=da)
797        #self.portal_workflow.doActionFor(application,'close',dest_container=application)
798        #
799        # personal
800        #
801        student_object.invokeFactory('StudentPersonal','personal')
802        personal = student_object.personal
803        #self.portal_workflow.doActionFor(personal,'open',dest_container=personal)
804        dp = {'Title': 'Personal Data'}
805        dp['sex'] = brain.sex
806        dp['email'] = brain.email
807        dp['phone'] = brain.phone
808        dp['lastname'] = brain.lastname
809        dp['middlename'] = brain.middlenames   # different field names!
810        dp['firstname'] = brain.firstname
811        personal.getContent().edit(mapping=dp)
812        #
813        # clearance
814        #
815        student_object.invokeFactory('StudentClearance','clearance')
816        clearance = student_object.clearance
817        #self.portal_workflow.doActionFor(clearance,'open',dest_container=clearance)
818        dc = {'Title': 'Clearance/Eligibility Record'}
819        dc['lga'] = brain.lga
820        clearance.getContent().edit(mapping=dc)
821        #self.portal_workflow.doActionFor(clearance,'close',dest_container=clearance)
822        #
823        # study Course
824        #
825        student_object.invokeFactory('StudentStudyCourse','study_course')
826        studycourse = student_object.study_course
827        #self.portal_workflow.doActionFor(studycourse,'open',dest_container=studycourse)
828        dsc = {}
829        dsc['study_course'] = brain.course_admitted
830        dsc['current_verdict'] = ''
831        dsc['current_mode'] = da['entry_mode']
832        if da['entry_mode'].startswith('de'):
833            dsc['current_level'] = '200'
834        else:
835            dsc['current_level'] = '100'
836        dsc['current_session'] = entry_session
837        studycourse.getContent().edit(mapping=dsc)
838        #
839        # payments folder
840        student_object.invokeFactory('PaymentsFolder','payments')
841        payments = getattr(student_object,'payments')
842        dpay = {}
843        dpay['Title'] = 'Payments'
844        payments.getContent().edit(mapping=dpay)
845        self.portal_workflow.doActionFor(payments,'open')
846        #
847        # passport foto
848        app_picture ="%s/import/images/%s/%s_passport.jpg" % (i_home,
849                                                              brain.screening_type,
850                                                              brain.reg_no)
851        images_dir = os.path.join("%s" % images_base,student_id)
852        if not os.path.exists(images_dir):
853            os.mkdir(images_dir)
854        image_name = os.path.join(images_dir,"passport_%(student_id)s.jpg" % vars())
855        if os.path.exists(app_picture):
856            copy2(app_picture,image_name)
857        else:
858            logger.info('passport of %s/%s not found: %s' % (student_id,
859                                                             brain.reg_no,
860                                                             app_picture))
861
862        return student_id
863    ###)
864
865    security.declareProtected(ModifyPortalContent,'makeStudentLevel') ###(
866    def makeStudentLevel(self,student_id):
867        "create the StudyLevel for a returning Student"
868        #import pdb;pdb.set_trace()
869        logger = logging.getLogger('WAeUPTool.makeStudentLevel')
870        students_folder = self.portal_url.getPortalObject().campus.students
871        res = self.students_catalog(id=student_id)
872        if res:
873            st = res[0]
874        course = st.course
875        matric_no = st.matric_no
876        level = st.level
877        res = self.results_import(matric_no = matric_no)
878        if res:
879            results = res
880        logger.info('%s creating Level %s' % (student_id,level))
881        #
882        # Level
883        #
884        student_obj = getattr(self.portal_url.getPortalObject().campus.students,student_id)
885        studycourse = getattr(student_obj,"study_course",None)
886        self.portal_workflow.doActionFor(studycourse,'close_for_edit',dest_container=studycourse)
887        l = getattr(studycourse,level,None)
888        if l is None:
889            studycourse.invokeFactory('StudentStudyLevel', level)
890            l = getattr(studycourse, level)
891            self.portal_workflow.doActionFor(l,'open',dest_container=l)
892            l.getContent().edit(mapping={'Title': "Level %s" % level})
893        ###)
894
895    security.declarePublic('getHallInfo') ###(
896    def getHallInfo(self,bed):
897        """return Hall Info"""
898        info = {}
899        hall,block,room,letter = bed.split('_')
900        res = ZCatalog.searchResults(self.portal_catalog_real,portal_type="AccoHall",id=hall)
901        if res and len(res) == 1:
902            hall_brain = res[0]
903            hall_doc = hall_brain.getObject().getContent()
904        else:
905            return info
906        info['hall_title'] = hall_brain.Title
907        info['maintenance_code'] = hall_doc.maintenance_code
908        res = ZCatalog.searchResults(self.portal_catalog_real,portal_type="ScratchCardBatch")
909        batch_doc = None
910        for brain in res:
911            if brain.id.startswith(info['maintenance_code']):
912                batch_doc = brain.getObject().getContent()
913                break
914        if batch_doc is None:
915            info['maintenance_fee'] = None
916        else:
917            info['maintenance_fee'] = batch_doc.cost
918        return info
919    ###)
920
921    security.declareProtected(ModifyPortalContent,'removePictureFolder') ###(
922    def removePictureFolder(self,student_id):
923        """remove picture_folder by renaming it"""
924        path = 'images'
925        picture_path = os.path.join(i_home,path,student_id)
926        if not os.path.exists(picture_path):
927            return False
928        os.rename(picture_path,picture_path + "_removed")
929        return True
930    ###)
931
932    security.declareProtected(ModifyPortalContent,'restorePictureFolder') ###(
933    def restorePictureFolder(self,student_id):
934        """restore picture_folder by renaming it"""
935        path = 'images'
936        picture_path = os.path.join(i_home,path,student_id)
937        if not os.path.exists(picture_path + "_removed"):
938            return False
939        os.rename(picture_path + "_removed",picture_path)
940        return True
941    ###)
942
943    security.declarePublic('picturesExist') ###(
944    def picturesExist(self, ids,student_id=None):
945        """check if pictures exist in the filesystem"""
946        if student_id is None:
947            student_id = self.getStudentId()
948        if student_id is None:
949            return False
950        picture_path = os.path.join(images_base,student_id)
951        if not os.path.exists(picture_path):
952            return False
953        pictures  = [picture[:picture.rfind('_')] for picture in os.listdir(picture_path)]
954        return set(ids).issubset(set(pictures))
955    ###)
956
957    security.declarePublic('picturesList') ###(
958    def picturesList(self):
959        """check if pictures exist in the filesystem"""
960        path = 'images'
961        student_id = self.getStudentId()
962        picture_path = os.path.join(i_home,path,student_id)
963        if not os.path.exists(picture_path):
964            return []
965        return [picture[:picture.rfind('_')] for picture in os.listdir(picture_path)]
966    ###)
967
968    security.declarePublic('showFsPicture') ###(
969    def showFsPicture(self,path):
970        """return a picture from the filesystem"""
971        picture_path = os.path.join(i_home,path)
972        response = self.REQUEST.RESPONSE
973        #import pdb;pdb.set_trace()
974        registry = getToolByName(self, 'mimetypes_registry')
975        mimetype = str(registry.lookupExtension(path.lower()) or
976                    registry.lookupExtension('file.bin'))
977        if os.path.exists(picture_path):
978            response.setHeader('Content-type',mimetype)
979            return open(picture_path).read()
980        picture_path = os.path.join(i_home,'import',path)
981        if os.path.exists(picture_path):
982            return open(picture_path).read()
983    ###)
984
985    security.declareProtected(ModifyPortalContent,'deleteAllCourses') ###(
986    def deleteAllCourses(self,department="All"):
987        ''' delete the courses'''
988        pm = self.portal_membership
989        member = pm.getAuthenticatedMember()
990
991        if str(member) not in ("henrik","joachim"):
992            return "not possible"
993        if department == "All":
994            res = self.portal_catalog({'meta_type': 'Department'})
995        if len(res) < 1:
996            return "No Departments found"
997
998        deleted = []
999        for dep in res:
1000            cf = dep.getObject().courses
1001            if cf:
1002                cf.manage_delObjects(ids=cf.objectIds())
1003                deleted.append("deleted Courses in %s" % dep.getId)
1004        return "\r".join(deleted)
1005    ###)
1006
1007    security.declareProtected(ModifyPortalContent,'getLogfileLines') ###(
1008    def getLogfileLines(self,filename="event.log",numlines=20):
1009        """Get last NUMLINES lines of logfile FILENAME.
1010
1011        Return last lines' of a file in the instances logfile directory as
1012        a list. The number of returned lines equals `numlines' or less. If
1013        less than `numlines' lines are available, the whole file ist
1014        returned. If the file can not be opened or some other error
1015        occurs, empty list is returend.
1016        """
1017        result = []
1018        lines_hit = 0
1019
1020        # We only handle files in instances' log directory...
1021        logpath = os.path.join(i_home, "log")
1022        filename = str(os.path.abspath( os.path.join( logpath, filename )))
1023        if not filename.startswith( logpath ):
1024            # Attempt to access file outside log-dir...
1025            return []
1026
1027        try:
1028            fd = file( filename, "rb" )
1029        except IOError:
1030            return []
1031        if not fd:
1032            return []
1033
1034        if os.linesep == None:
1035            linesep = '\n'
1036        else:
1037            linesep = os.linesep
1038
1039        # Try to find 'numlines' times a lineseparator, searching from end
1040        # and moving to the beginning of file...
1041        fd.seek( 0, 2) # Move to end of file...
1042        while lines_hit < numlines:
1043            if fd.read(1) == linesep[-1]: # This moves filedescriptor
1044                                          # one step forward...
1045                lines_hit += 1
1046            try:
1047                fd.seek( -2, 1) # Go two bytes back from current pos...
1048            except IOError:
1049                # We cannot go back two bytes. Maybe the file is too small...
1050                break
1051        fd.seek(2,1)
1052
1053        # Read all lines from current position...
1054        result = fd.readlines()
1055        # Remove line endings...
1056        result = [x.strip() for x in result]
1057        fd.close()
1058        return result
1059    ###)
1060
1061    security.declareProtected(ModifyPortalContent,"getCallbacksFromLog")###(
1062    def getCallbacksFromLog(self,filename):
1063        """fix Online Payment Transactions from Z2.log entries"""
1064        import transaction
1065        import random
1066        from cgi import parse_qs
1067        from urlparse import urlparse
1068        #from pdb import set_trace
1069        wftool = self.portal_workflow
1070        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1071        students_folder = self.portal_url.getPortalObject().campus.students
1072        s = r'(?P<client_ip>\S+) - (?P<member_id>\S+) \['
1073        s += r'(?P<date>.*)\] "(?P<get>.*)" (?P<codes>\d+ \d+) "'
1074        s += r'(?P<intersw>.*)" "(?P<agent>.*)"'
1075        data = re.compile(s)
1076        start = True
1077        tr_count = 1
1078        total = 0
1079        #name = 'pume_results'
1080        #name = 'epaymentsuccessful_z2log2'
1081        name = filename
1082        no_import = []
1083        imported = []
1084        logger = logging.getLogger('WAeUPTool.getFailedTransactions')
1085        try:
1086            transactions = open("%s/import/%s" % (i_home,name),"rb").readlines()
1087        except:
1088            logger.error('Error reading %s' % name)
1089            return
1090        tas = []
1091        for line in transactions:
1092            dict = {}
1093            items = data.search(line)
1094            dict['idict'] = idict = items.groupdict()
1095            #print idict
1096            #from pdb import set_trace;set_trace()
1097            urlparsed = urlparse(idict['get'][4:])
1098            #print urlparsed
1099            path = urlparsed[2].split('/')
1100            dict['student_id'] = student_id = path[8]
1101            dict['payment_id'] = payment_id = path[10]
1102            dict['qs_dict'] = qs_dict = parse_qs(urlparsed[4])
1103            tas.append(dict)
1104            tr_count += 1
1105        return tas
1106    ###)
1107
1108    security.declareProtected(ModifyPortalContent,"importOnlinePaymentTransactions")###(
1109    def importOnlinePaymentTransactions(self):
1110        """load Online Payment Transactions from CSV values"""
1111        import transaction
1112        import random
1113        #from pdb import set_trace
1114        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1115        opt = self.online_payments_import
1116        students_folder = self.portal_url.getPortalObject().campus.students
1117        start = True
1118        tr_count = 1
1119        total = 0
1120        #name = 'pume_results'
1121        name = 'OnlineTransactions'
1122        no_import = []
1123        imported = []
1124        logger = logging.getLogger('WAeUPTool.importOnlinePaymentTransactions')
1125        try:
1126            transactions = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
1127        except:
1128            logger.error('Error reading %s.csv' % name)
1129            return
1130        for pay_transaction in transactions:
1131            if start:
1132                start = False
1133                logger.info('Start loading from %s.csv' % name)
1134                s = ','.join(['"%s"' % fn for fn in pay_transaction.keys()])
1135                no_import.append('%s,"Error"' % s)
1136                format = ','.join(['"%%(%s)s"' % fn for fn in pay_transaction.keys()])
1137                format_error = format + ',"%(Error)s"'
1138            data = {}
1139
1140            # format of the first file sent by Tayo
1141            #data['datetime'] = date = DateTime.DateTime(pay_transaction['Date'])
1142            #data['student_id'] = student_id = pay_transaction['Payer ID']
1143            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
1144            #data['response_code'] = response_code = pay_transaction['Resp Code']
1145            #data['amount'] = amount = pay_transaction['Amount']
1146
1147            # format of the second file sent by Tayo
1148            #data['datetime'] = date = 0
1149            #data['student_id'] = student_id = pay_transaction['Payer ID']
1150            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
1151            #data['response_code'] = response_code = '00'
1152            #data['amount'] = amount = pay_transaction['Amount']
1153
1154            # format of the third file sent by Kehinde
1155            data['datetime'] = date = 0
1156            data['student_id'] = student_id = pay_transaction['customer_id']
1157            data['order_id'] = order_id = pay_transaction['merchant_reference']
1158            data['response_code'] = response_code = '00'
1159            data['amount'] = amount = pay_transaction['Amount']
1160
1161            dup = False
1162            if response_code == "12":
1163                continue
1164            try:
1165                opt.addRecord(**data)
1166            except ValueError:
1167                dup = True
1168            #from pdb import set_trace;set_trace()
1169            if dup:
1170                if response_code == "00":
1171                    try:
1172                        opt.modifyRecord(**data)
1173                    except:
1174                        logger.info("duplicate uid, order_id %(order_id)s, student_id %(student_id)s, response_code %(response_code)s" % data)
1175                        continue
1176                else:
1177                    pay_transaction['Error'] = "Duplicate order_id"
1178                    no_import.append( format_error % pay_transaction)
1179                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
1180                    continue
1181            tr_count += 1
1182            if tr_count > 1000:
1183                if len(no_import) > 0:
1184                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1185                             '\n'.join(no_import) + '\n')
1186                    no_import = []
1187                em = '%d transactions committed\n' % (tr_count)
1188                transaction.commit()
1189                regs = []
1190                logger.info(em)
1191                total += tr_count
1192                tr_count = 0
1193        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1194                                                '\n'.join(no_import))
1195        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
1196    ###)
1197
1198    security.declareProtected(ModifyPortalContent,'mass_create_faculty') ###(
1199    def mass_create_faculty(self,mapping):
1200        "create a faculty"
1201        logger = logging.getLogger('WAeUPTool.mass_create_faculty')
1202        academics_folder = self.portal_url.getPortalObject().campus.academics
1203        fid = mapping['code']
1204        if getattr(academics_folder,fid,None) is not None:
1205            return '', "Faculty with ID: %s exists" % fid
1206        logger.info('Creating Faculty %(code)s, %(title)s' % mapping)
1207        try:
1208            academics_folder.invokeFactory('Faculty', fid)
1209        except BadRequest,E:
1210            return '', "%s" % E
1211        f = getattr(academics_folder,fid,None)
1212        f.getContent().edit(mapping=mapping)
1213        return fid,''
1214    ###)
1215
1216    security.declareProtected(ModifyPortalContent,'mass_edit_faculty') ###(
1217    def mass_edit_faculty(self,mapping):
1218        "edit a faculty"
1219        logger = logging.getLogger('WAeUPTool.mass_edit_faculty')
1220        academics_folder = self.portal_url.getPortalObject().campus.academics
1221        fid = mapping['code']
1222        f = getattr(academics_folder,fid,None)
1223        if f is None:
1224            return '', "Faculty with ID: %s does not exist" % fid
1225        logger.info('Editing Faculty %(code)s, %(title)s' % mapping)
1226        f.getContent().edit(mapping=mapping)
1227        return fid,''
1228    ###)
1229
1230    security.declareProtected(ModifyPortalContent,'mass_create_department') ###(
1231    def mass_create_department(self,mapping):
1232        "create a department in the correct faculty"
1233        logger = logging.getLogger('WAeUPTool.mass_create_department')
1234        fid = mapping['faculty_code']
1235        if getattr(self,'_v_faculties',None) is None:
1236            res = self.portal_catalog(portal_type = "Faculty")
1237            self._v_faculties = {}
1238            for f in res:
1239                self._v_faculties[f.getId] = f.getObject()
1240        f = self._v_faculties.get(fid,None)
1241        if f is None:
1242            return '', "No Faculty with ID: %s" % fid
1243        else:
1244            did = mapping.get('code')
1245            d = getattr(f,did,None)
1246            if d is None or d.portal_type == "Faculty":
1247                logger.info('Creating Department %(code)s, %(title)s' % mapping)
1248                try:
1249                    f.invokeFactory('Department', did)
1250                except BadRequest,E:
1251                    return '', "%s" % E
1252                d = getattr(f,did)
1253                d.invokeFactory('CoursesFolder','courses')
1254                courses = getattr(d,'courses')
1255                dict = {'Title': 'Courses'}
1256                courses.getContent().edit(mapping=dict)
1257                d.invokeFactory('CertificatesFolder','certificates')
1258                certificates = getattr(d,'certificates')
1259                dict = {'Title': 'Certificates'}
1260                certificates.getContent().edit(mapping=dict)
1261            d.getContent().edit(mapping=mapping)
1262        return did,''
1263    ###)
1264
1265    security.declareProtected(ModifyPortalContent,'mass_edit_department') ###(
1266    def mass_edit_department(self,mapping):
1267        "create a department in the correct faculty"
1268        logger = logging.getLogger('WAeUPTool.mass_create_department')
1269        academics_folder = self.portal_url.getPortalObject().campus.academics
1270        fid = mapping['faculty_code']
1271        did = mapping.get('code')
1272        try:
1273            d = getattr(getattr(academics_folder,fid),did,None)
1274        except KeyError:
1275            return '', "Department %s or Faculty %s wrong" % (did,fid)
1276        else:
1277            if d is None or d.portal_type == "Faculty":
1278                logger.info('Editing Department %(code)s, %(title)s' % mapping)
1279            d.getContent().edit(mapping=mapping)
1280        return did,''
1281    ###)
1282
1283    security.declareProtected(ModifyPortalContent,'mass_create_course') ###(
1284    def mass_create_course(self,mapping):
1285        #import pdb;pdb.set_trace()
1286        if getattr(self,'_v_course_list',None) is None:
1287            self._v_course_list = []
1288        if getattr(self,'_v_departments',None) is None:
1289            res = self.portal_catalog(portal_type = "Department")
1290            self._v_department_courses = {}
1291            for d in res:
1292                self._v_department_courses[d.getId] = getattr(d.getObject(),"courses",None)
1293        did = mapping['department_code']
1294        d = self._v_department_courses.get(did,None)
1295        if d is None:
1296            return '', "No Department with ID: %s" % did
1297        course_id = mapping.get('code')
1298        if course_id in self._v_course_list:
1299            return '', "Duplicate Course ID: %s" % did
1300        c = getattr(d,course_id,None)
1301        if c is not None:
1302            return '', "Duplicate Course ID: %s" % did
1303        try:
1304            d.invokeFactory('Course', course_id)
1305        except BadRequest,E:
1306            return '', "%s" % E
1307        self._v_course_list.append(course_id)
1308        c = getattr(d,course_id)
1309        c.getContent().edit(mapping=mapping)
1310        return course_id,''
1311    ###)
1312
1313    security.declareProtected(ModifyPortalContent,'mass_edit_course') ###(
1314    def mass_edit_course(self,mapping):
1315        #import pdb;pdb.set_trace()
1316        course_id = mapping.get('code')
1317        res = self.portal_catalog(id=course_id)
1318        if not res:
1319            return '', "No Course with ID: %s" % course_id
1320        c = res[0].getObject()
1321        c.getContent().edit(mapping=mapping)
1322        return course_id,''
1323    ###)
1324
1325    security.declareProtected(ModifyPortalContent,'mass_create_certificate') ###(
1326    def mass_create_certificate(self,mapping):
1327        if getattr(self,'_v_certificate_list',None) is None:
1328            self._v_certificate_list = []
1329        if getattr(self,'_v_department_certificates',None) is None:
1330            res = self.portal_catalog(portal_type = "Department")
1331            self._v_department_certificates = {}
1332            for d in res:
1333                self._v_department_certificates[d.getId] = getattr(d.getObject(),"certificates",None)
1334        did = mapping['department_code']
1335        d = self._v_department_certificates.get(did,None)
1336        if d is None:
1337            return '', "No Department with ID: %s" % did
1338        certificate_id = mapping.get('code')
1339        if certificate_id in self._v_certificate_list:
1340            return '', "Duplicate Certificate ID: %s" % did
1341        c = getattr(d,certificate_id,None)
1342        if c is not None:
1343            return '', "Duplicate Certificate ID: %s" % did
1344        try:
1345            d.invokeFactory('Certificate', certificate_id)
1346        except BadRequest,E:
1347            return '', "%s" % E
1348        self._v_certificate_list.append(certificate_id)
1349        c = getattr(d,certificate_id)
1350        c.getContent().edit(mapping=mapping)
1351        return certificate_id,''
1352    ###)
1353
1354    security.declareProtected(ModifyPortalContent,'mass_edit_certificate') ###(
1355    def mass_edit_certificate(self,mapping):
1356        #import pdb;pdb.set_trace()
1357        certificate_id = mapping.get('code')
1358        res = self.portal_catalog(id=certificate_id)
1359        if not res:
1360            return '', "No Certificate with ID: %s" % did
1361        c = res[0].getObject()
1362        c.getContent().edit(mapping=mapping)
1363        return certificate_id,''
1364    ###)
1365
1366    security.declareProtected(ModifyPortalContent,'mass_create_application') ###(
1367    def mass_create_application(self,mapping):
1368        #import pdb;pdb.set_trace()
1369        reg_no = mapping.get('reg_no')
1370        try:
1371            self.applicants_catalog.addRecord(**mapping)
1372        except ValueError:
1373            return '', "applicant record with reg_no %s already exists" % reg_no
1374        return reg_no,''
1375    ###)
1376
1377    security.declareProtected(ModifyPortalContent,'mass_edit_application') ###(
1378    def mass_edit_application(self,mapping):
1379        #import pdb;pdb.set_trace()
1380        reg_no = mapping.get('reg_no')
1381        try:
1382            self.applicants_catalog.modifyRecord(**mapping)
1383        except KeyError:
1384            return '', "applicant record with reg_no %s does not exist" % reg_no
1385        return reg_no,''
1386    ###)
1387
1388    security.declareProtected(ModifyPortalContent,'mass_create_course_result') ###(
1389    def mass_create_course_result(self,mapping):
1390        #import pdb;pdb.set_trace()
1391        if getattr(self,'_v_courses',None) is None:
1392            res = self.courses_catalog()
1393            self._v_courses = {}
1394            for brain in res:
1395                self._v_courses[brain.code] = brain
1396        course_id = mapping.get('code')
1397        if course_id not in self._v_courses.keys():
1398            return '', "No course with ID: %s" % did
1399        id_key = ''
1400        for id_key in ('student_id','matric_no'):
1401            id_field = mapping.get(id_key,None)
1402            if id_field is not None:
1403                student_id = id_field
1404                break
1405        query = Eq(id_key,id_field)
1406        res = self.students_catalog.evalAdvancedQuery(query)
1407        if not res:
1408            return '', "No student with %(id_field)s: %(id_key)s" % vars()
1409        if id_field != "student_id":
1410            mapping['student_id'] = res[0].id
1411        mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % mapping
1412        for k in ('semester',):
1413            mapping[k] = getattr(self._v_courses[course_id],k)
1414        try:
1415            self.course_results.addRecord(**mapping)
1416        except ValueError:
1417            return '', "course result already exists: %s" % key
1418        return key,''
1419    ###)
1420
1421    security.declareProtected(ModifyPortalContent,'mass_edit_course_result') ###(
1422    def mass_edit_course_result(self,mapping):
1423        #import pdb;pdb.set_trace()
1424        # if getattr(self,'_v_courses',None) is None:
1425        #     res = self.courses_catalog()
1426        #     self._v_courses = {}
1427        #     for brain in res:
1428        #         self._v_courses[brain.code] = brain
1429        # course_id = mapping.get('code')
1430        # if course_id not in self._v_courses.keys():
1431        #     return '', "No course with ID: %s" % did
1432        id_key = ''
1433        for id_key in ('student_id','matric_no'):
1434            id_field = mapping.get(id_key,None)
1435            if id_field is not None:
1436                student_id = id_field
1437                break
1438        query = Eq(id_key,id_field)
1439        res = self.students_catalog.evalAdvancedQuery(query)
1440        if not res:
1441            return '', "No student with %(id_field)s: %(id_key)s" % vars()
1442        if id_field != "student_id":
1443            mapping['student_id'] = res[0].id
1444        mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % mapping
1445        # for k in ('semester',):
1446        #     mapping[k] = getattr(self._v_courses[course_id],k)
1447        try:
1448            self.course_results.modifyRecord(**mapping)
1449        except KeyError:
1450            return '', "No course result to edit: %s" % key
1451        return key,''
1452    ###)
1453
1454    security.declareProtected(ModifyPortalContent,'mass_create_certificate_course') ###(
1455    def mass_create_certificate_course(self,mapping):
1456        if getattr(self,'_v_courses',None) is None:
1457            res = self.courses_catalog()
1458            self._v_courses= [course.code for course in res]
1459        if getattr(self,'_v_ceritficates',None) is None:
1460            res = self.portal_catalog(portal_type = "Certificate")
1461            self._v_certificates = {}
1462            for cert in res:
1463                self._v_certificates[cert.getId] = cert.getObject()
1464        certificate_course_id = mapping.get('code')
1465        if certificate_course_id not in self._v_courses:
1466            return '', "No Course with ID: %s" % certificate_course_id
1467        cert_id = mapping['certificate_code']
1468        cert = self._v_certificates.get(cert_id,None)
1469        if cert is None:
1470            return '', "No Certificate with ID: %s" % cert_id
1471        level_id = mapping.get('level')
1472        level = getattr(cert,level_id,None)
1473        if level is None:
1474            cert.invokeFactory('StudyLevel', level_id)
1475            level = getattr(cert,level_id,None)
1476        elif hasattr(level,certificate_course_id):
1477            return '', "Duplicate CertificateCourse ID: %s in %s/ %s" %\
1478            (certificate_course_id,cert_id,level_id)
1479        level.invokeFactory('CertificateCourse', certificate_course_id)
1480        c = getattr(level,certificate_course_id)
1481        c.getContent().edit(mapping=mapping)
1482        return certificate_course_id,''
1483    ###)
1484
1485    field2types_student = {   ###(
1486                      'StudentApplication':
1487                          {'id': 'application',
1488                           'title': 'Application Data',
1489                           'wf_transition_return': 'close',
1490                           'wf_transition_admit': 'remain',
1491                           'fields':
1492                             ('jamb_reg_no',
1493                              'entry_mode',
1494                              'entry_session',
1495                              'jamb_score',
1496                              'app_email',
1497                              'jamb_age',
1498                              'jamb_state',
1499                              'jamb_lga',
1500                              )
1501                              },
1502                      #'StudentPume':
1503                      #    {'id': 'pume',
1504                      #     'title': 'Pume Data',
1505                      #     'wf_transition_return': 'close',
1506                      #     'wf_transition_admit': 'close',
1507                      #     'fields':
1508                      #       ('pume_score',
1509                      #        )
1510                      #        },
1511                      'StudentClearance':
1512                          {'id': 'clearance',
1513                           'title': 'Clearance/Eligibility Record',
1514                           'wf_transition_return': 'close',
1515                           'wf_transition_admit': 'remain',
1516                           'fields':
1517                             ('matric_no',
1518                              'nationality',
1519                              'lga',
1520                              'birthday',
1521                              )
1522                              },
1523                         'StudentPersonal':
1524                          {'id': 'personal',
1525                           'title': 'Personal Data',
1526                           'wf_transition_return': 'open',
1527                           'wf_transition_admit': 'remain',
1528                           'fields':
1529                             ('firstname',
1530                              'middlename',
1531                              'lastname',
1532                              'sex',
1533                              'email',
1534                              'phone',
1535                              'perm_address',
1536                              )
1537                              },
1538                         'StudentStudyCourse':
1539                          {'id': 'study_course',
1540                           'title': 'Study Course',
1541                           'wf_transition_return': 'open',
1542                           'wf_transition_admit': 'remain',
1543                           'fields':
1544                             ('study_course',
1545                              'current_level',
1546                              'current_session',
1547                              'current_mode',
1548                              'current_verdict',
1549                              'previous_verdict',
1550                              )
1551                              },
1552
1553                         'PaymentsFolder':
1554                          {'id': 'payments',
1555                           'title': 'Payments',
1556                           'wf_transition_return': 'open',
1557                           'wf_transition_admit': 'open',
1558                           'fields':
1559                             ()
1560                              },
1561                         }
1562    ###)
1563
1564    security.declareProtected(ModifyPortalContent,'mass_create_student') ###(
1565    def mass_create_student(self,mapping):
1566        "create a students record due import"
1567        logger = logging.getLogger('WAeUPTool.mass_create_student')
1568        students_folder = self.portal_url.getPortalObject().campus.students
1569        jamb_reg_no = mapping.get('jamb_reg_no',None)
1570        if jamb_reg_no:
1571            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1572            if res:
1573                return '',"jamb_reg_no exists"
1574        matric_no = mapping.get('matric_no',None)
1575        if matric_no:
1576            res = self.students_catalog(matric_no = matric_no)
1577            if res:
1578                return '',"matric_no exists"
1579        sid = self.waeup_tool.generateStudentId('?')
1580        students_folder.invokeFactory('Student', sid)
1581        student_obj = getattr(students_folder,sid)
1582        f2t = self.field2types_student
1583        d = {}
1584        transition = mapping.get('reg_transition','admit')
1585        if transition not in ('admit','return'):
1586            return '',"no valid transition provided"
1587        for pt in f2t.keys():
1588            student_obj.invokeFactory(pt,f2t[pt]['id'])
1589            sub_obj = getattr(student_obj,f2t[pt]['id'])
1590            sub_doc = sub_obj.getContent()
1591            d['Title'] = f2t[pt]['title']
1592            for field in f2t[pt]['fields']:
1593                d[field] = mapping.get(field,'')
1594
1595            if pt == "StudentApplication":
1596                d['jamb_sex']  = 'M'
1597                if mapping.get('sex'):
1598                    d['jamb_sex']  = 'F'
1599                d['jamb_firstname'] = mapping.get('firstname',None)
1600                d['jamb_middlename'] = mapping.get('middlename',None)
1601                d['jamb_lastname'] = mapping.get('lastname',None)
1602
1603            # if pt == "StudyCourse":
1604            #     for von,zu in (('entry_mode','current_mode'),
1605            #                    ('entry_session','current_session')):
1606            #         if mapping.get(zu,None) is None and mapping.get(von,None) is not None:
1607            #             d[zu] = mapping[von]
1608            sub_doc.edit(mapping = d)
1609
1610            #import pdb;pdb.set_trace()
1611            new_state = f2t[pt]['wf_transition_%(transition)s' % vars()]
1612            if new_state != "remain":
1613                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1614        self.portal_workflow.doActionFor(student_obj,transition)
1615        student_obj.manage_setLocalRoles(sid, ['Owner',])
1616        return sid,''
1617    ###)
1618
1619    security.declareProtected(ModifyPortalContent,'mass_edit_student') ###(
1620    def mass_edit_student(self,mapping):
1621        "edit a students record due import"
1622        logger = logging.getLogger('WAeUPTool.mass_edit_student')
1623        students_folder = self.portal_url.getPortalObject().campus.students
1624        sid = mapping.get('id',None)
1625        jamb_reg_no = mapping.get('jamb_reg_no',None)
1626        matric_no = mapping.get('matric_no',None)
1627        editable_keys = mapping.keys()
1628        if sid:
1629            res = self.students_catalog(id = sid)
1630            if not res:
1631                return '',"no student with id %s" % sid
1632            if matric_no and res[0].matric_no and\
1633              matric_no != res[0].matric_no:
1634                logger.info("%s, old matric_no %s overwritten with %s" % (res[0].id,res[0].matric_no,matric_no))
1635            if jamb_reg_no and res[0].jamb_reg_no and\
1636              jamb_reg_no != res[0].jamb_reg_no:
1637                logger.info("%s, old reg_no %s overwritten with %s" % (res[0].id,res[0].jamb_reg_no,jamb_reg_no))
1638        elif jamb_reg_no:
1639            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1640            if not res:
1641                return '',"no student with jamb_reg_no %s" % jamb_reg_no
1642            editable_keys.remove('jamb_reg_no')
1643        elif matric_no:
1644            res = self.students_catalog(matric_no = matric_no)
1645            if not res:
1646                return '',"no student with matric_no %s" % matric_no
1647            editable_keys.remove('matric_no')
1648
1649        ## included only to change wf state from admitted to returning
1650        #if res[0].review_state not in ('admitted','objection_raised'):
1651        #    return '%s' % res[0].id ,"student is not in state admitted or objection_raised"
1652        ## end inclusion
1653
1654        sid = res[0].id
1655        student_obj = getattr(students_folder,sid)
1656        f2t = self.field2types_student
1657        d = {}
1658        #import pdb;pdb.set_trace()
1659        any_change = False
1660        for pt in f2t.keys():
1661            if pt == "student_application":
1662                d['jamb_sex']  = 'M'
1663                if mapping.get('sex'):
1664                    d['jamb_sex']  = 'F'
1665            intersect = set(f2t[pt]['fields']).intersection(set(editable_keys))
1666            if intersect:
1667                sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1668                if sub_obj is None:
1669                    try:
1670                        student_obj.invokeFactory(pt,f2t[pt]['id'])
1671                    except:
1672                        continue
1673                    sub_obj = getattr(student_obj,f2t[pt]['id'])
1674                    d['Title'] = f2t[pt]['title']
1675                sub_doc = sub_obj.getContent()
1676                for field in intersect:
1677                    changed = False
1678                    if getattr(sub_doc,field,None) != mapping.get(field,''):
1679                        any_change = True
1680                        changed = True
1681                        d[field] = mapping.get(field,'')
1682                    if changed:
1683                        sub_doc.edit(mapping = d)
1684
1685
1686        ## included only to change wf state from admitted to returning
1687        #    if res[0].review_state in ('admitted','objection_raised'):
1688        #        new_state = f2t[pt]['wf_transition_return']
1689        #        sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1690        #        if sub_obj and new_state != "remain":
1691        #            try:
1692        #                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1693        #            except:
1694        #                #logger.info('%s, wf transition %s of %s failed' % (sid,new_state,sub_obj.id))
1695        #                pass
1696        #if res[0].review_state in ('admitted','objection_raised'):
1697        #    wfaction = 'return'
1698        #    try:
1699        #        self.portal_workflow.doActionFor(student_obj,wfaction)
1700        #        logger.info('%s, wf state changed' % sid)
1701        #        any_change = True
1702        #    except:
1703        #        logger.info('%s, wf transition failed, old state = %s' % (sid,res[0].review_state))
1704        #        pass
1705        ## end inclusion
1706
1707
1708        if any_change:
1709            return sid,''
1710        else:
1711            return sid,'not modified'
1712    ###)
1713
1714    security.declareProtected(ModifyPortalContent,"importData")###(
1715    def importData(self,filename,name,edit=False,bypass_queue_catalog=False):
1716        """load data from CSV values"""
1717        import transaction
1718        import random
1719
1720        pm = self.portal_membership
1721        member = pm.getAuthenticatedMember()
1722
1723        logger = logging.getLogger('WAeUPTool.importData')
1724        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1725        students_folder = self.portal_url.getPortalObject().campus.students
1726        start = True
1727        tr_count = 0
1728        total_imported = 0
1729        total_not_imported = 0
1730        total = 0
1731        iname = "import_%s" % name
1732        if iname == 'import_application':
1733            commit_after = 2000
1734        else:
1735            commit_after = 100
1736        stool = getToolByName(self, 'portal_schemas')
1737        ltool = getToolByName(self, 'portal_layouts')
1738        schema = stool._getOb(iname)
1739        if schema is None:
1740            em = 'No such schema %s' % iname
1741            logger.error('No such schema %s' % iname)
1742            return em
1743        layout = ltool._getOb(iname)
1744        if layout is None:
1745            em = 'No such layout %s' % iname
1746            logger.error(em)
1747            return em
1748        validators = {}
1749        for widget in layout.keys():
1750            validators[widget] = layout[widget].validate
1751        #import pdb;pdb.set_trace()
1752        mode = "create"
1753        if edit:
1754            mode = "edit"
1755        importer_name = "mass_%(mode)s_%(name)s" % vars()
1756        importer = getattr(self, '%s' % importer_name,None)
1757        if importer is None:
1758            em = 'No importer function %s' % importer_name
1759            logger.error(em)
1760            return em
1761        not_imported = []
1762        imported = []
1763        try:
1764            items = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
1765        except:
1766            em = 'Error reading %s.csv' % filename
1767            logger.error(em)
1768            return em
1769        for item in items:
1770            if start:
1771                start = False
1772                adapters = [MappingStorageAdapter(schema, item)]
1773                logger.info('%s starts import from %s.csv in %s mode with schema and layout %s' % (member,filename,mode,iname))
1774                attrs = csv.reader(open("%s/import/%s.csv" % (i_home,filename),"rb")).next()
1775                import_keys = [k for k in attrs if not k.startswith('ignore')]
1776                diff2schema = set(import_keys).difference(set(schema.keys()))
1777                diff2layout = set(import_keys).difference(set(layout.keys()))
1778                if diff2schema:
1779                    em = 'not ignorable key(s): "%s" found in heading' % ", ".join(diff2schema)
1780                    return em
1781                if mode == "create":
1782                    required_keys = [layout.getIdUnprefixed(id)
1783                                     for id,widget in layout.objectItems()
1784                                     if widget.is_required]
1785                    if not set(required_keys).issubset(set(import_keys)):
1786                        diff2import = set(required_keys).difference(set(import_keys))
1787                        em = 'required key(s): "%s" not found in heading' % ", ".join(diff2import)
1788                        return em
1789                s = ','.join(['"%s"' % fn for fn in import_keys])
1790                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(s + ',"Error"'+ '\n')
1791                s = '"id",' + s
1792                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
1793                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
1794                format_error = format + ',"%(Error)s"'
1795                format = '"%(id)s",'+ format
1796
1797            dm = DataModel(item, adapters,context=self)
1798            ds = DataStructure(data=item,datamodel=dm)
1799            error_string = ""
1800            total += 1
1801            for k in import_keys:
1802                if not validators[k](ds,mode=mode):
1803                    error_string += " %s : %s" % (k,
1804                                                  self.translation_service(ds.getError(k),
1805                                                                           ds.getErrorMapping(k)))
1806            if not error_string:
1807                temp_item = item.copy()
1808                temp_item.update(dm)
1809                temp_item['id'],error = importer(temp_item)
1810                if error:
1811                    error_string += error
1812                else:
1813                    item = temp_item
1814            if error_string:
1815                item['Error'] = error_string
1816                not_imported.append(format_error % item)
1817                total_not_imported += 1
1818            else:
1819                em = format % item
1820                imported.append(em)
1821                tr_count += 1
1822                total_imported += 1
1823                logger.info("%(total_imported)d of %(total)d %(em)s" % vars())
1824
1825            if total and not total % commit_after:
1826                transaction.commit()
1827                if len(not_imported) > 0:
1828                    open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1829                             '\n'.join(not_imported) + '\n')
1830                    not_imported = []
1831                if len(imported) > 0:
1832                    open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
1833                             '\n'.join(imported) + '\n')
1834                    imported = []
1835                em = '%d transactions committed\n' % (tr_count)
1836                regs = []
1837                logger.info(em)
1838                tr_count = 0
1839                #if total > 100:
1840                #    return
1841        if len(imported) > 0:
1842            open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
1843                                                '\n'.join(imported))
1844        if len(not_imported) > 0:
1845            open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1846                                                '\n'.join(not_imported))
1847        em = "Finished: %d imported, %d not imported (of total %d)" % (total_imported,total_not_imported,total)
1848        logger.info(em)
1849        return em
1850    ###)
1851
1852    security.declareProtected(ModifyPortalContent,"moveImagesToFS")###(
1853    def moveImagesToFS(self,student_id="O738726"):
1854        "move the images to the filesystem"
1855        images_dir = os.path.join("%s" % images_base,student_id)
1856        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1857        stool = getToolByName(self, 'portal_schemas')
1858        schemas = ['student_application',
1859                   'student_clearance',
1860                   ]
1861        created = False
1862        for schema_id in schemas:
1863            schema = stool._getOb(schema_id)
1864            object = getattr(student_folder,schema_id[len('student_'):],None)
1865            if object is None:
1866                continue
1867            doc = object.getContent()
1868            for key in schema.keys():
1869                if schema[key].meta_type != "CPS Image Field":
1870                    continue
1871                #import pdb;pdb.set_trace()
1872                image = getattr(doc,key,None)
1873                if not image or not hasattr(image,"data"):
1874                    continue
1875                if not created:
1876                    if not os.path.exists(images_dir):
1877                        os.mkdir(images_dir)
1878                    created = True
1879                filename = os.path.join(images_dir,"%(key)s_%(student_id)s.jpg" % vars())
1880                open(filename,"wb").write(str(image.data))
1881    ###)
1882
1883    security.declareProtected(ModifyPortalContent,"movePassportToFS")###(
1884    def movePassportToFS(self,student_id="O738726"):
1885        "move the passports to the filesystem"
1886        images_dir = os.path.join("%s" % i_home,'passports')
1887        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1888        stool = getToolByName(self, 'portal_schemas')
1889        schemas = ['student_application',
1890                   #'student_clearance',
1891                   ]
1892        created = False
1893        for schema_id in schemas:
1894            schema = stool._getOb(schema_id)
1895            object = getattr(student_folder,schema_id[len('student_'):],None)
1896            if object is None:
1897                continue
1898            doc = object.getContent()
1899            for key in schema.keys():
1900                if schema[key].meta_type != "CPS Image Field":
1901                    continue
1902                #import pdb;pdb.set_trace()
1903                image = getattr(doc,key)
1904                if not hasattr(image,"data"):
1905                    continue
1906                if not created:
1907                    if not os.path.exists(images_dir):
1908                        os.mkdir(images_dir)
1909                    created = True
1910                filename = os.path.join(images_dir,"%(student_id)s.jpg" % vars())
1911                open(filename,"wb").write(str(image.data))
1912    ###)
1913
1914InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.