source: WAeUP_SRP/base/WAeUPTool.py @ 2676

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

new images directory structure

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