source: WAeUP_SRP/base/WAeUPTool.py @ 2660

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

Several modifications made to enable payment for all sessions, all payment modes and both portals I tested all combinations.

'N/A' replaced by in level, verdict and session widgets. A missing value is now always .

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