source: WAeUP_SRP/base/WAeUPTool.py @ 2677

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

fix picturesList

  • Property svn:keywords set to Id
File size: 79.0 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 2677 2007-11-16 12:05:36Z 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        picture_path = getImagesDir(student_id)
970        if not os.path.exists(picture_path):
971            return []
972        return [picture[:picture.rfind('_')] for picture in os.listdir(picture_path)]
973    ###)
974
975    security.declarePublic('showFsPicture') ###(
976    def showFsPicture(self,path):
977        """return a picture from the filesystem"""
978        #picture_path = os.path.join(i_home,path)
979        picture_path = os.path.join(images_base,path)
980        response = self.REQUEST.RESPONSE
981        #import pdb;pdb.set_trace()
982        registry = getToolByName(self, 'mimetypes_registry')
983        mimetype = str(registry.lookupExtension(path.lower()) or
984                    registry.lookupExtension('file.bin'))
985        if os.path.exists(picture_path):
986            response.setHeader('Content-type',mimetype)
987            return open(picture_path).read()
988        picture_path = os.path.join(i_home,'import',path)
989        if os.path.exists(picture_path):
990            return open(picture_path).read()
991    ###)
992
993    security.declareProtected(ModifyPortalContent,'deleteAllCourses') ###(
994    def deleteAllCourses(self,department="All"):
995        ''' delete the courses'''
996        pm = self.portal_membership
997        member = pm.getAuthenticatedMember()
998
999        if str(member) not in ("henrik","joachim"):
1000            return "not possible"
1001        if department == "All":
1002            res = self.portal_catalog({'meta_type': 'Department'})
1003        if len(res) < 1:
1004            return "No Departments found"
1005
1006        deleted = []
1007        for dep in res:
1008            cf = dep.getObject().courses
1009            if cf:
1010                cf.manage_delObjects(ids=cf.objectIds())
1011                deleted.append("deleted Courses in %s" % dep.getId)
1012        return "\r".join(deleted)
1013    ###)
1014
1015    security.declareProtected(ModifyPortalContent,'getLogfileLines') ###(
1016    def getLogfileLines(self,filename="event.log",numlines=20):
1017        """Get last NUMLINES lines of logfile FILENAME.
1018
1019        Return last lines' of a file in the instances logfile directory as
1020        a list. The number of returned lines equals `numlines' or less. If
1021        less than `numlines' lines are available, the whole file ist
1022        returned. If the file can not be opened or some other error
1023        occurs, empty list is returend.
1024        """
1025        result = []
1026        lines_hit = 0
1027
1028        # We only handle files in instances' log directory...
1029        logpath = os.path.join(i_home, "log")
1030        filename = str(os.path.abspath( os.path.join( logpath, filename )))
1031        if not filename.startswith( logpath ):
1032            # Attempt to access file outside log-dir...
1033            return []
1034
1035        try:
1036            fd = file( filename, "rb" )
1037        except IOError:
1038            return []
1039        if not fd:
1040            return []
1041
1042        if os.linesep == None:
1043            linesep = '\n'
1044        else:
1045            linesep = os.linesep
1046
1047        # Try to find 'numlines' times a lineseparator, searching from end
1048        # and moving to the beginning of file...
1049        fd.seek( 0, 2) # Move to end of file...
1050        while lines_hit < numlines:
1051            if fd.read(1) == linesep[-1]: # This moves filedescriptor
1052                                          # one step forward...
1053                lines_hit += 1
1054            try:
1055                fd.seek( -2, 1) # Go two bytes back from current pos...
1056            except IOError:
1057                # We cannot go back two bytes. Maybe the file is too small...
1058                break
1059        fd.seek(2,1)
1060
1061        # Read all lines from current position...
1062        result = fd.readlines()
1063        # Remove line endings...
1064        result = [x.strip() for x in result]
1065        fd.close()
1066        return result
1067    ###)
1068
1069    security.declareProtected(ModifyPortalContent,"getCallbacksFromLog")###(
1070    def getCallbacksFromLog(self,filename):
1071        """fix Online Payment Transactions from Z2.log entries"""
1072        import transaction
1073        import random
1074        from cgi import parse_qs
1075        from urlparse import urlparse
1076        #from pdb import set_trace
1077        wftool = self.portal_workflow
1078        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1079        students_folder = self.portal_url.getPortalObject().campus.students
1080        s = r'(?P<client_ip>\S+) - (?P<member_id>\S+) \['
1081        s += r'(?P<date>.*)\] "(?P<get>.*)" (?P<codes>\d+ \d+) "'
1082        s += r'(?P<intersw>.*)" "(?P<agent>.*)"'
1083        data = re.compile(s)
1084        start = True
1085        tr_count = 1
1086        total = 0
1087        #name = 'pume_results'
1088        #name = 'epaymentsuccessful_z2log2'
1089        name = filename
1090        no_import = []
1091        imported = []
1092        logger = logging.getLogger('WAeUPTool.getFailedTransactions')
1093        try:
1094            transactions = open("%s/import/%s" % (i_home,name),"rb").readlines()
1095        except:
1096            logger.error('Error reading %s' % name)
1097            return
1098        tas = []
1099        for line in transactions:
1100            dict = {}
1101            items = data.search(line)
1102            dict['idict'] = idict = items.groupdict()
1103            #print idict
1104            #from pdb import set_trace;set_trace()
1105            urlparsed = urlparse(idict['get'][4:])
1106            #print urlparsed
1107            path = urlparsed[2].split('/')
1108            dict['student_id'] = student_id = path[8]
1109            dict['payment_id'] = payment_id = path[10]
1110            dict['qs_dict'] = qs_dict = parse_qs(urlparsed[4])
1111            tas.append(dict)
1112            tr_count += 1
1113        return tas
1114    ###)
1115
1116    security.declareProtected(ModifyPortalContent,"importOnlinePaymentTransactions")###(
1117    def importOnlinePaymentTransactions(self):
1118        """load Online Payment Transactions from CSV values"""
1119        import transaction
1120        import random
1121        #from pdb import set_trace
1122        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1123        opt = self.online_payments_import
1124        students_folder = self.portal_url.getPortalObject().campus.students
1125        start = True
1126        tr_count = 1
1127        total = 0
1128        #name = 'pume_results'
1129        name = 'OnlineTransactions'
1130        no_import = []
1131        imported = []
1132        logger = logging.getLogger('WAeUPTool.importOnlinePaymentTransactions')
1133        try:
1134            transactions = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
1135        except:
1136            logger.error('Error reading %s.csv' % name)
1137            return
1138        for pay_transaction in transactions:
1139            if start:
1140                start = False
1141                logger.info('Start loading from %s.csv' % name)
1142                s = ','.join(['"%s"' % fn for fn in pay_transaction.keys()])
1143                no_import.append('%s,"Error"' % s)
1144                format = ','.join(['"%%(%s)s"' % fn for fn in pay_transaction.keys()])
1145                format_error = format + ',"%(Error)s"'
1146            data = {}
1147
1148            # format of the first file sent by Tayo
1149            #data['datetime'] = date = DateTime.DateTime(pay_transaction['Date'])
1150            #data['student_id'] = student_id = pay_transaction['Payer ID']
1151            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
1152            #data['response_code'] = response_code = pay_transaction['Resp Code']
1153            #data['amount'] = amount = pay_transaction['Amount']
1154
1155            # format of the second file sent by Tayo
1156            #data['datetime'] = date = 0
1157            #data['student_id'] = student_id = pay_transaction['Payer ID']
1158            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
1159            #data['response_code'] = response_code = '00'
1160            #data['amount'] = amount = pay_transaction['Amount']
1161
1162            # format of the third file sent by Kehinde
1163            data['datetime'] = date = 0
1164            data['student_id'] = student_id = pay_transaction['customer_id']
1165            data['order_id'] = order_id = pay_transaction['merchant_reference']
1166            data['response_code'] = response_code = '00'
1167            data['amount'] = amount = pay_transaction['Amount']
1168
1169            dup = False
1170            if response_code == "12":
1171                continue
1172            try:
1173                opt.addRecord(**data)
1174            except ValueError:
1175                dup = True
1176            #from pdb import set_trace;set_trace()
1177            if dup:
1178                if response_code == "00":
1179                    try:
1180                        opt.modifyRecord(**data)
1181                    except:
1182                        logger.info("duplicate uid, order_id %(order_id)s, student_id %(student_id)s, response_code %(response_code)s" % data)
1183                        continue
1184                else:
1185                    pay_transaction['Error'] = "Duplicate order_id"
1186                    no_import.append( format_error % pay_transaction)
1187                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
1188                    continue
1189            tr_count += 1
1190            if tr_count > 1000:
1191                if len(no_import) > 0:
1192                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1193                             '\n'.join(no_import) + '\n')
1194                    no_import = []
1195                em = '%d transactions committed\n' % (tr_count)
1196                transaction.commit()
1197                regs = []
1198                logger.info(em)
1199                total += tr_count
1200                tr_count = 0
1201        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1202                                                '\n'.join(no_import))
1203        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
1204    ###)
1205
1206    security.declareProtected(ModifyPortalContent,'mass_create_faculty') ###(
1207    def mass_create_faculty(self,mapping):
1208        "create a faculty"
1209        logger = logging.getLogger('WAeUPTool.mass_create_faculty')
1210        academics_folder = self.portal_url.getPortalObject().campus.academics
1211        fid = mapping['code']
1212        if getattr(academics_folder,fid,None) is not None:
1213            return '', "Faculty with ID: %s exists" % fid
1214        logger.info('Creating Faculty %(code)s, %(title)s' % mapping)
1215        try:
1216            academics_folder.invokeFactory('Faculty', fid)
1217        except BadRequest,E:
1218            return '', "%s" % E
1219        f = getattr(academics_folder,fid,None)
1220        f.getContent().edit(mapping=mapping)
1221        return fid,''
1222    ###)
1223
1224    security.declareProtected(ModifyPortalContent,'mass_edit_faculty') ###(
1225    def mass_edit_faculty(self,mapping):
1226        "edit a faculty"
1227        logger = logging.getLogger('WAeUPTool.mass_edit_faculty')
1228        academics_folder = self.portal_url.getPortalObject().campus.academics
1229        fid = mapping['code']
1230        f = getattr(academics_folder,fid,None)
1231        if f is None:
1232            return '', "Faculty with ID: %s does not exist" % fid
1233        logger.info('Editing Faculty %(code)s, %(title)s' % mapping)
1234        f.getContent().edit(mapping=mapping)
1235        return fid,''
1236    ###)
1237
1238    security.declareProtected(ModifyPortalContent,'mass_create_department') ###(
1239    def mass_create_department(self,mapping):
1240        "create a department in the correct faculty"
1241        logger = logging.getLogger('WAeUPTool.mass_create_department')
1242        fid = mapping['faculty_code']
1243        if getattr(self,'_v_faculties',None) is None:
1244            res = self.portal_catalog(portal_type = "Faculty")
1245            self._v_faculties = {}
1246            for f in res:
1247                self._v_faculties[f.getId] = f.getObject()
1248        f = self._v_faculties.get(fid,None)
1249        if f is None:
1250            return '', "No Faculty with ID: %s" % fid
1251        else:
1252            did = mapping.get('code')
1253            d = getattr(f,did,None)
1254            if d is None or d.portal_type == "Faculty":
1255                logger.info('Creating Department %(code)s, %(title)s' % mapping)
1256                try:
1257                    f.invokeFactory('Department', did)
1258                except BadRequest,E:
1259                    return '', "%s" % E
1260                d = getattr(f,did)
1261                d.invokeFactory('CoursesFolder','courses')
1262                courses = getattr(d,'courses')
1263                dict = {'Title': 'Courses'}
1264                courses.getContent().edit(mapping=dict)
1265                d.invokeFactory('CertificatesFolder','certificates')
1266                certificates = getattr(d,'certificates')
1267                dict = {'Title': 'Certificates'}
1268                certificates.getContent().edit(mapping=dict)
1269            d.getContent().edit(mapping=mapping)
1270        return did,''
1271    ###)
1272
1273    security.declareProtected(ModifyPortalContent,'mass_edit_department') ###(
1274    def mass_edit_department(self,mapping):
1275        "create a department in the correct faculty"
1276        logger = logging.getLogger('WAeUPTool.mass_create_department')
1277        academics_folder = self.portal_url.getPortalObject().campus.academics
1278        fid = mapping['faculty_code']
1279        did = mapping.get('code')
1280        try:
1281            d = getattr(getattr(academics_folder,fid),did,None)
1282        except KeyError:
1283            return '', "Department %s or Faculty %s wrong" % (did,fid)
1284        else:
1285            if d is None or d.portal_type == "Faculty":
1286                logger.info('Editing Department %(code)s, %(title)s' % mapping)
1287            d.getContent().edit(mapping=mapping)
1288        return did,''
1289    ###)
1290
1291    security.declareProtected(ModifyPortalContent,'mass_create_course') ###(
1292    def mass_create_course(self,mapping):
1293        #import pdb;pdb.set_trace()
1294        if getattr(self,'_v_course_list',None) is None:
1295            self._v_course_list = []
1296        if getattr(self,'_v_departments',None) is None:
1297            res = self.portal_catalog(portal_type = "Department")
1298            self._v_department_courses = {}
1299            for d in res:
1300                self._v_department_courses[d.getId] = getattr(d.getObject(),"courses",None)
1301        did = mapping['department_code']
1302        d = self._v_department_courses.get(did,None)
1303        if d is None:
1304            return '', "No Department with ID: %s" % did
1305        course_id = mapping.get('code')
1306        if course_id in self._v_course_list:
1307            return '', "Duplicate Course ID: %s" % did
1308        c = getattr(d,course_id,None)
1309        if c is not None:
1310            return '', "Duplicate Course ID: %s" % did
1311        try:
1312            d.invokeFactory('Course', course_id)
1313        except BadRequest,E:
1314            return '', "%s" % E
1315        self._v_course_list.append(course_id)
1316        c = getattr(d,course_id)
1317        c.getContent().edit(mapping=mapping)
1318        return course_id,''
1319    ###)
1320
1321    security.declareProtected(ModifyPortalContent,'mass_edit_course') ###(
1322    def mass_edit_course(self,mapping):
1323        #import pdb;pdb.set_trace()
1324        course_id = mapping.get('code')
1325        res = self.portal_catalog(id=course_id)
1326        if not res:
1327            return '', "No Course with ID: %s" % course_id
1328        c = res[0].getObject()
1329        c.getContent().edit(mapping=mapping)
1330        return course_id,''
1331    ###)
1332
1333    security.declareProtected(ModifyPortalContent,'mass_create_certificate') ###(
1334    def mass_create_certificate(self,mapping):
1335        if getattr(self,'_v_certificate_list',None) is None:
1336            self._v_certificate_list = []
1337        if getattr(self,'_v_department_certificates',None) is None:
1338            res = self.portal_catalog(portal_type = "Department")
1339            self._v_department_certificates = {}
1340            for d in res:
1341                self._v_department_certificates[d.getId] = getattr(d.getObject(),"certificates",None)
1342        did = mapping['department_code']
1343        d = self._v_department_certificates.get(did,None)
1344        if d is None:
1345            return '', "No Department with ID: %s" % did
1346        certificate_id = mapping.get('code')
1347        if certificate_id in self._v_certificate_list:
1348            return '', "Duplicate Certificate ID: %s" % did
1349        c = getattr(d,certificate_id,None)
1350        if c is not None:
1351            return '', "Duplicate Certificate ID: %s" % did
1352        try:
1353            d.invokeFactory('Certificate', certificate_id)
1354        except BadRequest,E:
1355            return '', "%s" % E
1356        self._v_certificate_list.append(certificate_id)
1357        c = getattr(d,certificate_id)
1358        c.getContent().edit(mapping=mapping)
1359        return certificate_id,''
1360    ###)
1361
1362    security.declareProtected(ModifyPortalContent,'mass_edit_certificate') ###(
1363    def mass_edit_certificate(self,mapping):
1364        #import pdb;pdb.set_trace()
1365        certificate_id = mapping.get('code')
1366        res = self.portal_catalog(id=certificate_id)
1367        if not res:
1368            return '', "No Certificate with ID: %s" % did
1369        c = res[0].getObject()
1370        c.getContent().edit(mapping=mapping)
1371        return certificate_id,''
1372    ###)
1373
1374    security.declareProtected(ModifyPortalContent,'mass_create_application') ###(
1375    def mass_create_application(self,mapping):
1376        #import pdb;pdb.set_trace()
1377        reg_no = mapping.get('reg_no')
1378        try:
1379            self.applicants_catalog.addRecord(**mapping)
1380        except ValueError:
1381            return '', "applicant record with reg_no %s already exists" % reg_no
1382        return reg_no,''
1383    ###)
1384
1385    security.declareProtected(ModifyPortalContent,'mass_edit_application') ###(
1386    def mass_edit_application(self,mapping):
1387        #import pdb;pdb.set_trace()
1388        reg_no = mapping.get('reg_no')
1389        try:
1390            self.applicants_catalog.modifyRecord(**mapping)
1391        except KeyError:
1392            return '', "applicant record with reg_no %s does not exist" % reg_no
1393        return reg_no,''
1394    ###)
1395
1396    security.declareProtected(ModifyPortalContent,'mass_create_course_result') ###(
1397    def mass_create_course_result(self,mapping):
1398        #import pdb;pdb.set_trace()
1399        if getattr(self,'_v_courses',None) is None:
1400            res = self.courses_catalog()
1401            self._v_courses = {}
1402            for brain in res:
1403                self._v_courses[brain.code] = brain
1404        course_id = mapping.get('code')
1405        if course_id not in self._v_courses.keys():
1406            return '', "No course with ID: %s" % did
1407        id_key = ''
1408        for id_key in ('student_id','matric_no'):
1409            id_field = mapping.get(id_key,None)
1410            if id_field is not None:
1411                student_id = id_field
1412                break
1413        query = Eq(id_key,id_field)
1414        res = self.students_catalog.evalAdvancedQuery(query)
1415        if not res:
1416            return '', "No student with %(id_field)s: %(id_key)s" % vars()
1417        if id_field != "student_id":
1418            mapping['student_id'] = res[0].id
1419        mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % mapping
1420        for k in ('semester',):
1421            mapping[k] = getattr(self._v_courses[course_id],k)
1422        try:
1423            self.course_results.addRecord(**mapping)
1424        except ValueError:
1425            return '', "course result already exists: %s" % key
1426        return key,''
1427    ###)
1428
1429    security.declareProtected(ModifyPortalContent,'mass_edit_course_result') ###(
1430    def mass_edit_course_result(self,mapping):
1431        #import pdb;pdb.set_trace()
1432        # if getattr(self,'_v_courses',None) is None:
1433        #     res = self.courses_catalog()
1434        #     self._v_courses = {}
1435        #     for brain in res:
1436        #         self._v_courses[brain.code] = brain
1437        # course_id = mapping.get('code')
1438        # if course_id not in self._v_courses.keys():
1439        #     return '', "No course with ID: %s" % did
1440        id_key = ''
1441        for id_key in ('student_id','matric_no'):
1442            id_field = mapping.get(id_key,None)
1443            if id_field is not None:
1444                student_id = id_field
1445                break
1446        query = Eq(id_key,id_field)
1447        res = self.students_catalog.evalAdvancedQuery(query)
1448        if not res:
1449            return '', "No student with %(id_field)s: %(id_key)s" % vars()
1450        if id_field != "student_id":
1451            mapping['student_id'] = res[0].id
1452        mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % mapping
1453        # for k in ('semester',):
1454        #     mapping[k] = getattr(self._v_courses[course_id],k)
1455        try:
1456            self.course_results.modifyRecord(**mapping)
1457        except KeyError:
1458            return '', "No course result to edit: %s" % key
1459        return key,''
1460    ###)
1461
1462    security.declareProtected(ModifyPortalContent,'mass_create_certificate_course') ###(
1463    def mass_create_certificate_course(self,mapping):
1464        if getattr(self,'_v_courses',None) is None:
1465            res = self.courses_catalog()
1466            self._v_courses= [course.code for course in res]
1467        if getattr(self,'_v_ceritficates',None) is None:
1468            res = self.portal_catalog(portal_type = "Certificate")
1469            self._v_certificates = {}
1470            for cert in res:
1471                self._v_certificates[cert.getId] = cert.getObject()
1472        certificate_course_id = mapping.get('code')
1473        if certificate_course_id not in self._v_courses:
1474            return '', "No Course with ID: %s" % certificate_course_id
1475        cert_id = mapping['certificate_code']
1476        cert = self._v_certificates.get(cert_id,None)
1477        if cert is None:
1478            return '', "No Certificate with ID: %s" % cert_id
1479        level_id = mapping.get('level')
1480        level = getattr(cert,level_id,None)
1481        if level is None:
1482            cert.invokeFactory('StudyLevel', level_id)
1483            level = getattr(cert,level_id,None)
1484        elif hasattr(level,certificate_course_id):
1485            return '', "Duplicate CertificateCourse ID: %s in %s/ %s" %\
1486            (certificate_course_id,cert_id,level_id)
1487        level.invokeFactory('CertificateCourse', certificate_course_id)
1488        c = getattr(level,certificate_course_id)
1489        c.getContent().edit(mapping=mapping)
1490        return certificate_course_id,''
1491    ###)
1492
1493    field2types_student = {   ###(
1494                      'StudentApplication':
1495                          {'id': 'application',
1496                           'title': 'Application Data',
1497                           'wf_transition_return': 'close',
1498                           'wf_transition_admit': 'remain',
1499                           'fields':
1500                             ('jamb_reg_no',
1501                              'entry_mode',
1502                              'entry_session',
1503                              'jamb_score',
1504                              'app_email',
1505                              'jamb_age',
1506                              'jamb_state',
1507                              'jamb_lga',
1508                              )
1509                              },
1510                      #'StudentPume':
1511                      #    {'id': 'pume',
1512                      #     'title': 'Pume Data',
1513                      #     'wf_transition_return': 'close',
1514                      #     'wf_transition_admit': 'close',
1515                      #     'fields':
1516                      #       ('pume_score',
1517                      #        )
1518                      #        },
1519                      'StudentClearance':
1520                          {'id': 'clearance',
1521                           'title': 'Clearance/Eligibility Record',
1522                           'wf_transition_return': 'close',
1523                           'wf_transition_admit': 'remain',
1524                           'fields':
1525                             ('matric_no',
1526                              'nationality',
1527                              'lga',
1528                              'birthday',
1529                              )
1530                              },
1531                         'StudentPersonal':
1532                          {'id': 'personal',
1533                           'title': 'Personal Data',
1534                           'wf_transition_return': 'open',
1535                           'wf_transition_admit': 'remain',
1536                           'fields':
1537                             ('firstname',
1538                              'middlename',
1539                              'lastname',
1540                              'sex',
1541                              'email',
1542                              'phone',
1543                              'perm_address',
1544                              )
1545                              },
1546                         'StudentStudyCourse':
1547                          {'id': 'study_course',
1548                           'title': 'Study Course',
1549                           'wf_transition_return': 'open',
1550                           'wf_transition_admit': 'remain',
1551                           'fields':
1552                             ('study_course',
1553                              'current_level',
1554                              'current_session',
1555                              'current_mode',
1556                              'current_verdict',
1557                              'previous_verdict',
1558                              )
1559                              },
1560
1561                         'PaymentsFolder':
1562                          {'id': 'payments',
1563                           'title': 'Payments',
1564                           'wf_transition_return': 'open',
1565                           'wf_transition_admit': 'open',
1566                           'fields':
1567                             ()
1568                              },
1569                         }
1570    ###)
1571
1572    security.declareProtected(ModifyPortalContent,'mass_create_student') ###(
1573    def mass_create_student(self,mapping):
1574        "create a students record due import"
1575        logger = logging.getLogger('WAeUPTool.mass_create_student')
1576        students_folder = self.portal_url.getPortalObject().campus.students
1577        jamb_reg_no = mapping.get('jamb_reg_no',None)
1578        if jamb_reg_no:
1579            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1580            if res:
1581                return '',"jamb_reg_no exists"
1582        matric_no = mapping.get('matric_no',None)
1583        if matric_no:
1584            res = self.students_catalog(matric_no = matric_no)
1585            if res:
1586                return '',"matric_no exists"
1587        sid = self.waeup_tool.generateStudentId('?')
1588        students_folder.invokeFactory('Student', sid)
1589        student_obj = getattr(students_folder,sid)
1590        f2t = self.field2types_student
1591        d = {}
1592        transition = mapping.get('reg_transition','admit')
1593        if transition not in ('admit','return'):
1594            return '',"no valid transition provided"
1595        for pt in f2t.keys():
1596            student_obj.invokeFactory(pt,f2t[pt]['id'])
1597            sub_obj = getattr(student_obj,f2t[pt]['id'])
1598            sub_doc = sub_obj.getContent()
1599            d['Title'] = f2t[pt]['title']
1600            for field in f2t[pt]['fields']:
1601                d[field] = mapping.get(field,'')
1602
1603            if pt == "StudentApplication":
1604                d['jamb_sex']  = 'M'
1605                if mapping.get('sex'):
1606                    d['jamb_sex']  = 'F'
1607                d['jamb_firstname'] = mapping.get('firstname',None)
1608                d['jamb_middlename'] = mapping.get('middlename',None)
1609                d['jamb_lastname'] = mapping.get('lastname',None)
1610
1611            # if pt == "StudyCourse":
1612            #     for von,zu in (('entry_mode','current_mode'),
1613            #                    ('entry_session','current_session')):
1614            #         if mapping.get(zu,None) is None and mapping.get(von,None) is not None:
1615            #             d[zu] = mapping[von]
1616            sub_doc.edit(mapping = d)
1617
1618            #import pdb;pdb.set_trace()
1619            new_state = f2t[pt]['wf_transition_%(transition)s' % vars()]
1620            if new_state != "remain":
1621                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1622        self.portal_workflow.doActionFor(student_obj,transition)
1623        student_obj.manage_setLocalRoles(sid, ['Owner',])
1624        return sid,''
1625    ###)
1626
1627    security.declareProtected(ModifyPortalContent,'mass_edit_student') ###(
1628    def mass_edit_student(self,mapping):
1629        "edit a students record due import"
1630        logger = logging.getLogger('WAeUPTool.mass_edit_student')
1631        students_folder = self.portal_url.getPortalObject().campus.students
1632        sid = mapping.get('id',None)
1633        jamb_reg_no = mapping.get('jamb_reg_no',None)
1634        matric_no = mapping.get('matric_no',None)
1635        editable_keys = mapping.keys()
1636        if sid:
1637            res = self.students_catalog(id = sid)
1638            if not res:
1639                return '',"no student with id %s" % sid
1640            if matric_no and res[0].matric_no and\
1641              matric_no != res[0].matric_no:
1642                logger.info("%s, old matric_no %s overwritten with %s" % (res[0].id,res[0].matric_no,matric_no))
1643            if jamb_reg_no and res[0].jamb_reg_no and\
1644              jamb_reg_no != res[0].jamb_reg_no:
1645                logger.info("%s, old reg_no %s overwritten with %s" % (res[0].id,res[0].jamb_reg_no,jamb_reg_no))
1646        elif jamb_reg_no:
1647            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1648            if not res:
1649                return '',"no student with jamb_reg_no %s" % jamb_reg_no
1650            editable_keys.remove('jamb_reg_no')
1651        elif matric_no:
1652            res = self.students_catalog(matric_no = matric_no)
1653            if not res:
1654                return '',"no student with matric_no %s" % matric_no
1655            editable_keys.remove('matric_no')
1656
1657        ## included only to change wf state from admitted to returning
1658        #if res[0].review_state not in ('admitted','objection_raised'):
1659        #    return '%s' % res[0].id ,"student is not in state admitted or objection_raised"
1660        ## end inclusion
1661
1662        sid = res[0].id
1663        student_obj = getattr(students_folder,sid)
1664        f2t = self.field2types_student
1665        d = {}
1666        #import pdb;pdb.set_trace()
1667        any_change = False
1668        for pt in f2t.keys():
1669            if pt == "student_application":
1670                d['jamb_sex']  = 'M'
1671                if mapping.get('sex'):
1672                    d['jamb_sex']  = 'F'
1673            intersect = set(f2t[pt]['fields']).intersection(set(editable_keys))
1674            if intersect:
1675                sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1676                if sub_obj is None:
1677                    try:
1678                        student_obj.invokeFactory(pt,f2t[pt]['id'])
1679                    except:
1680                        continue
1681                    sub_obj = getattr(student_obj,f2t[pt]['id'])
1682                    d['Title'] = f2t[pt]['title']
1683                sub_doc = sub_obj.getContent()
1684                for field in intersect:
1685                    changed = False
1686                    if getattr(sub_doc,field,None) != mapping.get(field,''):
1687                        any_change = True
1688                        changed = True
1689                        d[field] = mapping.get(field,'')
1690                    if changed:
1691                        sub_doc.edit(mapping = d)
1692
1693
1694        ## included only to change wf state from admitted to returning
1695        #    if res[0].review_state in ('admitted','objection_raised'):
1696        #        new_state = f2t[pt]['wf_transition_return']
1697        #        sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1698        #        if sub_obj and new_state != "remain":
1699        #            try:
1700        #                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1701        #            except:
1702        #                #logger.info('%s, wf transition %s of %s failed' % (sid,new_state,sub_obj.id))
1703        #                pass
1704        #if res[0].review_state in ('admitted','objection_raised'):
1705        #    wfaction = 'return'
1706        #    try:
1707        #        self.portal_workflow.doActionFor(student_obj,wfaction)
1708        #        logger.info('%s, wf state changed' % sid)
1709        #        any_change = True
1710        #    except:
1711        #        logger.info('%s, wf transition failed, old state = %s' % (sid,res[0].review_state))
1712        #        pass
1713        ## end inclusion
1714
1715
1716        if any_change:
1717            return sid,''
1718        else:
1719            return sid,'not modified'
1720    ###)
1721
1722    security.declareProtected(ModifyPortalContent,"importData")###(
1723    def importData(self,filename,name,edit=False,bypass_queue_catalog=False):
1724        """load data from CSV values"""
1725        import transaction
1726        import random
1727
1728        pm = self.portal_membership
1729        member = pm.getAuthenticatedMember()
1730
1731        logger = logging.getLogger('WAeUPTool.importData')
1732        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1733        students_folder = self.portal_url.getPortalObject().campus.students
1734        start = True
1735        tr_count = 0
1736        total_imported = 0
1737        total_not_imported = 0
1738        total = 0
1739        iname = "import_%s" % name
1740        if iname == 'import_application':
1741            commit_after = 2000
1742        else:
1743            commit_after = 100
1744        stool = getToolByName(self, 'portal_schemas')
1745        ltool = getToolByName(self, 'portal_layouts')
1746        schema = stool._getOb(iname)
1747        if schema is None:
1748            em = 'No such schema %s' % iname
1749            logger.error('No such schema %s' % iname)
1750            return em
1751        layout = ltool._getOb(iname)
1752        if layout is None:
1753            em = 'No such layout %s' % iname
1754            logger.error(em)
1755            return em
1756        validators = {}
1757        for widget in layout.keys():
1758            validators[widget] = layout[widget].validate
1759        #import pdb;pdb.set_trace()
1760        mode = "create"
1761        if edit:
1762            mode = "edit"
1763        importer_name = "mass_%(mode)s_%(name)s" % vars()
1764        importer = getattr(self, '%s' % importer_name,None)
1765        if importer is None:
1766            em = 'No importer function %s' % importer_name
1767            logger.error(em)
1768            return em
1769        not_imported = []
1770        imported = []
1771        try:
1772            items = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
1773        except:
1774            em = 'Error reading %s.csv' % filename
1775            logger.error(em)
1776            return em
1777        for item in items:
1778            if start:
1779                start = False
1780                adapters = [MappingStorageAdapter(schema, item)]
1781                logger.info('%s starts import from %s.csv in %s mode with schema and layout %s' % (member,filename,mode,iname))
1782                attrs = csv.reader(open("%s/import/%s.csv" % (i_home,filename),"rb")).next()
1783                import_keys = [k for k in attrs if not k.startswith('ignore')]
1784                diff2schema = set(import_keys).difference(set(schema.keys()))
1785                diff2layout = set(import_keys).difference(set(layout.keys()))
1786                if diff2schema:
1787                    em = 'not ignorable key(s): "%s" found in heading' % ", ".join(diff2schema)
1788                    return em
1789                if mode == "create":
1790                    required_keys = [layout.getIdUnprefixed(id)
1791                                     for id,widget in layout.objectItems()
1792                                     if widget.is_required]
1793                    if not set(required_keys).issubset(set(import_keys)):
1794                        diff2import = set(required_keys).difference(set(import_keys))
1795                        em = 'required key(s): "%s" not found in heading' % ", ".join(diff2import)
1796                        return em
1797                s = ','.join(['"%s"' % fn for fn in import_keys])
1798                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(s + ',"Error"'+ '\n')
1799                s = '"id",' + s
1800                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
1801                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
1802                format_error = format + ',"%(Error)s"'
1803                format = '"%(id)s",'+ format
1804
1805            dm = DataModel(item, adapters,context=self)
1806            ds = DataStructure(data=item,datamodel=dm)
1807            error_string = ""
1808            total += 1
1809            for k in import_keys:
1810                if not validators[k](ds,mode=mode):
1811                    error_string += " %s : %s" % (k,
1812                                                  self.translation_service(ds.getError(k),
1813                                                                           ds.getErrorMapping(k)))
1814            if not error_string:
1815                temp_item = item.copy()
1816                temp_item.update(dm)
1817                temp_item['id'],error = importer(temp_item)
1818                if error:
1819                    error_string += error
1820                else:
1821                    item = temp_item
1822            if error_string:
1823                item['Error'] = error_string
1824                not_imported.append(format_error % item)
1825                total_not_imported += 1
1826            else:
1827                em = format % item
1828                imported.append(em)
1829                tr_count += 1
1830                total_imported += 1
1831                logger.info("%(total_imported)d of %(total)d %(em)s" % vars())
1832
1833            if total and not total % commit_after:
1834                transaction.commit()
1835                if len(not_imported) > 0:
1836                    open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1837                             '\n'.join(not_imported) + '\n')
1838                    not_imported = []
1839                if len(imported) > 0:
1840                    open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
1841                             '\n'.join(imported) + '\n')
1842                    imported = []
1843                em = '%d transactions committed\n' % (tr_count)
1844                regs = []
1845                logger.info(em)
1846                tr_count = 0
1847                #if total > 100:
1848                #    return
1849        if len(imported) > 0:
1850            open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
1851                                                '\n'.join(imported))
1852        if len(not_imported) > 0:
1853            open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1854                                                '\n'.join(not_imported))
1855        em = "Finished: %d imported, %d not imported (of total %d)" % (total_imported,total_not_imported,total)
1856        logger.info(em)
1857        return em
1858    ###)
1859
1860    security.declareProtected(ModifyPortalContent,"moveImagesToFS")###(
1861    def moveImagesToFS(self,student_id="O738726"):
1862        "move the images to the filesystem"
1863        images_dir = getImagesDir(student_id)
1864        #images_dir = os.path.join("%s" % images_base,student_id)
1865        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1866        stool = getToolByName(self, 'portal_schemas')
1867        schemas = ['student_application',
1868                   'student_clearance',
1869                   ]
1870        created = False
1871        for schema_id in schemas:
1872            schema = stool._getOb(schema_id)
1873            object = getattr(student_folder,schema_id[len('student_'):],None)
1874            if object is None:
1875                continue
1876            doc = object.getContent()
1877            for key in schema.keys():
1878                if schema[key].meta_type != "CPS Image Field":
1879                    continue
1880                #import pdb;pdb.set_trace()
1881                image = getattr(doc,key,None)
1882                if not image or not hasattr(image,"data"):
1883                    continue
1884                if not created:
1885                    if not os.path.exists(images_dir):
1886                        os.mkdir(images_dir)
1887                    created = True
1888                filename = os.path.join(images_dir,"%(key)s_%(student_id)s.jpg" % vars())
1889                open(filename,"wb").write(str(image.data))
1890    ###)
1891
1892    security.declareProtected(ModifyPortalContent,"movePassportToFS")###(
1893    def movePassportToFS(self,student_id="O738726"):
1894        "move the passports to the filesystem"
1895        images_dir = os.path.join("%s" % i_home,'passports')
1896        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1897        stool = getToolByName(self, 'portal_schemas')
1898        schemas = ['student_application',
1899                   #'student_clearance',
1900                   ]
1901        created = False
1902        for schema_id in schemas:
1903            schema = stool._getOb(schema_id)
1904            object = getattr(student_folder,schema_id[len('student_'):],None)
1905            if object is None:
1906                continue
1907            doc = object.getContent()
1908            for key in schema.keys():
1909                if schema[key].meta_type != "CPS Image Field":
1910                    continue
1911                #import pdb;pdb.set_trace()
1912                image = getattr(doc,key)
1913                if not hasattr(image,"data"):
1914                    continue
1915                if not created:
1916                    if not os.path.exists(images_dir):
1917                        os.mkdir(images_dir)
1918                    created = True
1919                filename = os.path.join(images_dir,"%(student_id)s.jpg" % vars())
1920                open(filename,"wb").write(str(image.data))
1921    ###)
1922
1923InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.