source: WAeUP_SRP/base/WAeUPTool.py @ 2706

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

resolve ticket #405

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