source: WAeUP_SRP/base/WAeUPTool.py @ 2711

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

see ticket #398

Joachim, please check!

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