source: WAeUP_SRP/trunk/WAeUPTool.py @ 5165

Last change on this file since 5165 was 5165, checked in by Henrik Bettermann, 15 years ago

implement temporary application module only for 2008 sandwich applicants so that they can remain in the system

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