source: WAeUP_SRP/base/WAeUPTool.py @ 2673

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

further modifications for session change

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