source: WAeUP_SRP/trunk/WAeUPTool.py @ 5058

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

don't create accommodation object

  • Property svn:keywords set to Id
File size: 77.6 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 5023 2010-02-18 22:15:18Z 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        return member_record.getProperty('fullname',None)
746    ###)
747
748
749    security.declarePublic('makeStudentMember') ###(
750    def makeStudentMember(self,sid,password='uNsEt'):
751        """make the student a member"""
752        membership = self.portal_membership
753        membership.addMember(sid,
754                             password ,
755                             roles=('Member',
756                                     'Student',
757                                     ),
758                             domains='',
759                             properties = {'memberareaCreationFlag': False,
760                                           'homeless': True},)
761        member = membership.getMemberById(sid)
762        self.portal_registration.afterAdd(member, sid, password, None)
763        #self.manage_setLocalRoles(sid, ['Owner',])
764    ###)
765
766    security.declareProtected(View,'makeStudentData') ###(
767    def makeStudentData(self,student_id,email=None,phone_nr=None):
768        "create Datastructure for a returning Student"
769        #import pdb;pdb.set_trace()
770        logger = logging.getLogger('WAeUPTool.makeStudentData')
771        students_folder = self.portal_url.getPortalObject().campus.students
772        #res = self.students_catalog(id=student_id)
773        #if res:
774        #    st = res[0]
775        #res = self.returning_import(matric_no = st.matric_no)
776        res = self.returning_import(id = student_id)
777        if res:
778            student = res[0]
779        else:
780            logger.info('Id %s not found in returning_import' % student_id)
781            return
782        logger.info('%s creates data structure' % student_id)
783        s_results = self.results_import(matric_no = student.matric_no)
784        if s_results:
785            lnr = self.getLevelFromResultsCosCode(s_results)
786            level = "%d00" % lnr
787            verdict,eligible = self.getVerdict(s_results[0].Verdict)
788            #if eligible:
789            #    level = "%d00" % (lnr + 1)
790        else:
791            logger.info('matric_no %s not found in results_import' % student.matric_no)
792            level = ''
793            verdict = ''
794        #student should not be allowed to perform this transition
795        #wftool = self.portal_workflow
796        #wftool.doActionFor(student,'return')
797        certcode_org = student.Coursemajorcode
798        certcode = makeCertificateCode(certcode_org)
799        certificate_brain = self.getCertificateBrain(certcode)
800        if not certificate_brain:
801            em = 'Certificate %s org-code %s not found\n' % (certcode, certcode_org)
802            logger.info(em)
803        matric_no = student.matric_no
804        sid = student_id
805        student_obj = getattr(students_folder,sid)
806        if not getattr(student_obj,'application'):
807            student_obj.invokeFactory('StudentApplication','application')
808        application = student_obj.application
809        self.portal_workflow.doActionFor(application,'open',dest_container=application)
810        da = {'Title': 'Application Data'}
811        student_obj.invokeFactory('StudentPersonal','personal')
812        da['jamb_reg_no'] = student.Entryregno
813        em = self.getEntryMode(student.Entryregno)
814        da['entry_mode'] = em
815        personal = student_obj.personal
816        self.portal_workflow.doActionFor(personal,'open',dest_container=personal)
817        dp = {'Title': 'Personal Data'}
818        student_obj.invokeFactory('StudentClearance','clearance')
819        clearance = student_obj.clearance
820        self.portal_workflow.doActionFor(clearance,'open',dest_container=clearance)
821        dc = {'Title': 'Clearance/Eligibility Record'}
822        dc['matric_no'] = matric_no
823        state = student.State
824        lga = student.LGA
825        if state and lga:
826            lga =  state + ' / ' + lga
827        else:
828            lga = "None"
829        da['jamb_lga'] = dc['lga'] = lga
830        da['app_email'] = dp['email'] = email
831        da['app_mobile'] = dp['phone'] = phone_nr
832        dp['firstname'] = student.Firstname
833        dp['middlename'] = student.Middlename
834        dp['lastname'] = student.Lastname
835        da['jamb_lastname'] = "%s %s %s" % (student.Firstname,student.Middlename,student.Lastname)
836        da['jamb_sex'] = student.Sex
837        dp['sex'] = student.Sex == 'F'
838        dp['perm_address'] = student.Permanent_Address
839        application.getContent().edit(mapping=da)
840        self.portal_workflow.doActionFor(application,'close',dest_container=application)
841        personal.getContent().edit(mapping=dp)
842        clearance.getContent().edit(mapping=dc)
843        self.portal_workflow.doActionFor(clearance,'close',dest_container=clearance)
844        #
845        # Study Course
846        #
847        student_obj.invokeFactory('StudentStudyCourse','study_course')
848        studycourse = student_obj.study_course
849        self.portal_workflow.doActionFor(studycourse,'open',dest_container=studycourse)
850        dsc = {}
851        dsc['study_course'] = certcode
852        dsc['current_level'] = level
853        dsc['current_verdict'] = verdict
854        dsc['current_mode'] = em   #no longer used
855        dsc['current_session'] = '05'
856        studycourse.getContent().edit(mapping=dsc)
857        #
858        # Level
859        #
860        # l = getattr(studycourse,level,None)
861        # if l is None:
862        #     studycourse.invokeFactory('StudentStudyLevel', level)
863        #     l = getattr(studycourse, level)
864        #     self.portal_workflow.doActionFor(l,'open',dest_container=l)
865        #     l.getContent().edit(mapping={'Title': "Level %s" % level})
866        ###)
867
868    def init_timing(self): ###(
869        if self.with_timing:
870            if not hasattr(self,'_v_step_times'):
871                self._v_timer_count = 0
872                self._v_total = 0
873                self._v_step_times = {}
874                current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
875                self._v_timer_file = "%s/export/timing_%s.csv" % (i_home,current,)
876            self.timer_step = 0
877            self.total_time = 0
878            self.elapse = time.time()
879            self.i_elapse = time.time()
880            self.c_elapse = time.clock()
881    ###)
882
883    def do_timing(self): ###(
884        if self.with_timing:
885            try:
886                raise 'dummy'
887            except:
888                frame = sys.exc_traceback.tb_frame.f_back
889                locals = frame.f_locals
890                globals = frame.f_globals
891                functionname = frame.f_code.co_name
892                filename = os.path.basename(frame.f_code.co_filename)
893                lineno = frame.f_lineno
894                mod_line = "%(functionname)s:%(lineno)s" % vars()
895            i_time = time.time() - self.i_elapse
896            td = {}
897            if self._v_step_times.has_key(mod_line):
898                a_time = self._v_step_times[mod_line]['a_time'] + i_time
899                td['a_time'] = a_time
900            else:
901                td['a_time'] = i_time
902            td['i_time'] = i_time
903            self._v_step_times[mod_line] = td
904            self.i_time = i_time
905            self.total_time += i_time
906            self.timer_step +=1
907            self.i_elapse = time.time()
908    ###)
909
910    security.declareProtected(ModifyPortalContent,'print_timing') ###( ###(
911    def print_timing(self):
912        if self.with_timing:
913            l = []
914            timer_count = self._v_timer_count + 1
915            mod_lines = self._v_step_times.keys()
916            mod_lines.sort(cmp,reverse=0)
917            for mod_line in mod_lines:
918                td = self._v_step_times[mod_line]
919                i_time = td['i_time']
920                a_time = td['a_time']/(self._v_timer_count + 1)
921                l += ("%(mod_line)s,%(i_time)6.2f,%(a_time)6.2f,%(timer_count)d" % vars()),
922            total_time = self.total_time
923            total_avarage = self._v_total / timer_count
924            l += ("total,%(total_time)6.4f,%(total_avarage)6.4f,%(timer_count)d" % vars()),
925            print "\r\n".join(l)
926            out = open(self._v_timer_file,'a')
927            out.write("\r\n".join(l))
928            out.close()
929    ###)
930
931    security.declareProtected(ModifyPortalContent,'get_timing_data') ###( ###(
932    def get_timing_data(self):
933        if self.with_timing:
934            timer_count = self._v_timer_count + 1
935            results = {}
936            for k,d in self._v_step_times.items():
937                dd = {}
938                dd['a_time'] = d['a_time']/timer_count
939                dd['i_time'] = d['i_time']
940                dd['count'] = timer_count
941                results[k] = dd
942            dd = {}
943            dd['a_time'] = self._v_total / timer_count
944            dd['i_time'] = self.total_time
945            dd['count'] = timer_count
946            results["total"] = dd
947            return results
948    ###)
949
950    security.declareProtected(ModifyPortalContent,'admitOneStudent') ###(
951    def admitOneStudent(self,brain,entry_session,pin_password,with_timing=False):
952        "create Datastructure for an admitted Student"
953        #import pdb;pdb.set_trace()
954        logger = logging.getLogger('WAeUPTool.admitOneStudent')
955        self.with_timing = with_timing
956
957        try:
958            if brain.screening_type in ('cest','sandwich',) and brain.serial and brain.entry_session:
959                if brain.course1:
960                    reg_no = "%s%s/%s" % (brain.course1[:3],brain.serial,brain.entry_session)
961                else:
962                    reg_no = "%s%s/%s" % (brain.course_admitted[:3],brain.serial,brain.entry_session)
963            else:
964                reg_no = brain.reg_no
965        except:
966            logger.info('applicant record %s has errors' % (brain.reg_no))
967            return
968
969        #ignore argument entry_session
970        if not brain.entry_session:
971            logger.info('no entry_session for %s provided' % (reg_no))
972            return
973        else:
974            es = brain.entry_session
975        if len(es) == 1:
976            es = '0%c' % es
977
978        if not hasattr(self,"_v_certificates"):
979            self._v_certificates = self.getCertificatesDict()
980        students_folder = self.portal_url.getPortalObject().campus.students
981
982        res = self.students_catalog(jamb_reg_no = reg_no)
983        if res:
984            logger.info('student with reg_no %s exists (%s)' % (reg_no,res[0].id))
985            return
986        if brain.status != "admitted":
987            logger.info('status of %s is %s' % (reg_no,brain.status))
988            return
989        pin_parts = brain.pin.split('-')
990        if pin_parts and len(pin_parts) != 3:
991            logger.info('invalid pin %s for %s' % (brain.pin,reg_no))
992            return
993        if not brain.course_admitted:
994            logger.info('no course_admitted provided for %s' % (reg_no))
995            return           
996        if brain.course_admitted not in self._v_certificates:
997            logger.info('certificate %s not found for %s' % (brain.course_admitted,reg_no))
998            return
999        if brain.sex not in (True,False):
1000            logger.info('sex of %s not available' % (reg_no))
1001            return
1002        self.init_timing()
1003        student_id = self.generateStudentId('?')
1004        students_folder.invokeFactory('Student', student_id)
1005        student_object = getattr(students_folder,student_id)
1006        self.do_timing()
1007        if pin_password:
1008            password = pin_parts[2]
1009            self.makeStudentMember(student_id,password = password)
1010        student_object.manage_setLocalRoles(student_id, ['Owner',])
1011        self.do_timing()
1012        #logger.info("creating %s reg_no %s" % (student_id,reg_no))
1013        #
1014        # application
1015        #
1016        student_object.invokeFactory('StudentApplication','application')
1017        application = student_object.application
1018        #self.portal_workflow.doActionFor(application,'open',dest_container=application)
1019        #self.do_timing()
1020        da = {'Title': 'Application Data'}
1021        da['jamb_reg_no'] = reg_no
1022
1023        sex = 'M'
1024        if brain.sex:
1025            sex = 'F'
1026        da['jamb_sex'] = sex
1027        da['jamb_age'] = brain.jamb_age
1028        da['app_reg_pin'] = brain.pin
1029        da['jamb_lga'] = brain.jamb_lga
1030        da['jamb_state'] = brain.jamb_state
1031        da['jamb_score'] = brain.aggregate
1032        da['app_email'] = brain.email
1033        da['app_mobile'] = brain.phone
1034
1035        # entry_mode cannot be retrieved from the certtificate
1036        # because ug_ft has two different entry modes
1037                       
1038        if brain.entry_mode:                      # does not happen because import_application
1039            da['entry_mode'] = brain.entry_mode   # schema has no field entry_mode
1040        elif brain.screening_type == 'pume': 
1041            da['entry_mode'] = 'ume_ft' 
1042        elif brain.screening_type == 'pde': 
1043            da['entry_mode'] = 'de_ft' 
1044        else:
1045            da['entry_mode'] = self._v_certificates[brain.course_admitted]['study_mode']
1046       
1047        #elif brain.screening_type == 'pce': 
1048        #   da['entry_mode'] = 'pce' 
1049        #elif brain.screening_type == 'prence': 
1050        #   da['entry_mode'] = 'prence' 
1051        #else: 
1052        #   da['entry_mode'] = '' 
1053     
1054
1055        #da['entry_session'] = entry_session
1056        da['entry_session'] = es
1057        da['jamb_lastname'] = brain.lastname
1058        da['jamb_middlename'] = brain.middlenames   # different field names!
1059        da['jamb_firstname'] = brain.firstname
1060        da['screening_application_date'] = brain.application_date
1061        da['date_of_birth'] = brain.date_of_birth
1062        da['jamb_first_cos'] = brain.course1
1063        da['jamb_second_cos'] = brain.course2
1064        da['course3'] = brain.course3
1065        da['screening_type'] = brain.screening_type
1066        da['screening_score'] = brain.screening_score
1067        da['screening_date'] = brain.screening_date
1068        da['hq_type'] = brain.hq_type
1069        da['hq_grade'] = brain.hq_grade
1070        da['aos'] = brain.aos
1071
1072        application.getContent().edit(mapping=da)
1073        self.do_timing()
1074        #self.portal_workflow.doActionFor(application,'close',dest_container=application)
1075        #
1076        # personal
1077        #
1078        student_object.invokeFactory('StudentPersonal','personal')
1079        personal = student_object.personal
1080        #self.portal_workflow.doActionFor(personal,'open',dest_container=personal)
1081        #self.do_timing()
1082        dp = {'Title': 'Personal Data'}
1083        dp['sex'] = brain.sex
1084        dp['email'] = brain.email
1085        dp['phone'] = brain.phone
1086        dp['lastname'] = brain.lastname
1087        dp['middlename'] = brain.middlenames   # different field names!
1088        dp['firstname'] = brain.firstname
1089        personal.getContent().edit(mapping=dp)
1090        self.do_timing()
1091        #
1092        # clearance
1093        #
1094        student_object.invokeFactory('StudentClearance','clearance')
1095        clearance = student_object.clearance
1096        #self.portal_workflow.doActionFor(clearance,'open',dest_container=clearance)
1097        dc = {'Title': 'Clearance/Eligibility Record'}
1098        dc['lga'] = brain.lga
1099        dc['birthday'] = brain.date_of_birth
1100        clearance.getContent().edit(mapping=dc)
1101        self.do_timing()
1102        #self.portal_workflow.doActionFor(clearance,'close',dest_container=clearance)
1103        #
1104        # study Course
1105        #
1106        student_object.invokeFactory('StudentStudyCourse','study_course')
1107        studycourse = student_object.study_course
1108        #self.portal_workflow.doActionFor(studycourse,'open',dest_container=studycourse)
1109        #self.do_timing()
1110        dsc = {}
1111        dsc['study_course'] = brain.course_admitted
1112        dsc['current_verdict'] = ''
1113        dsc['current_mode'] = da['entry_mode'] # no longer used
1114        if da['entry_mode'].startswith('de'):
1115            dsc['current_level'] = '200'
1116        elif da['entry_mode'].startswith('pre'):
1117            dsc['current_level'] = '000'
1118        else:
1119            dsc['current_level'] = '100'
1120        dsc['current_session'] = es
1121        studycourse.getContent().edit(mapping=dsc)
1122        self.do_timing()
1123        #
1124        # payments folder
1125        student_object.invokeFactory('PaymentsFolder','payments')
1126        payments = getattr(student_object,'payments')
1127        #self.do_timing()
1128        dpay = {}
1129        dpay['Title'] = 'Payments'
1130        payments.getContent().edit(mapping=dpay)
1131        self.portal_workflow.doActionFor(payments,'open')
1132        self.do_timing()
1133        #
1134        # passport foto
1135        app_picture ="%s/import/images/%s/%s_passport.jpg" % (i_home,
1136                                                              brain.screening_type,
1137                                                              brain.reg_no)
1138        images_dir = getImagesDir(student_id)
1139        #images_dir = os.path.join("%s" % images_base,student_id)
1140        letter_dir,student_dir = os.path.split(images_dir)
1141        if not os.path.exists(letter_dir):
1142            os.mkdir(letter_dir)
1143        if not os.path.exists(images_dir):
1144            os.mkdir(images_dir)
1145        image_name = os.path.join(images_dir,"passport_%(student_id)s.jpg" % vars())
1146        if os.path.exists(app_picture):
1147            copy2(app_picture,image_name)
1148        else:
1149            logger.info('passport of %s/%s not found: %s' % (student_id,
1150                                                             brain.reg_no,
1151                                                             app_picture))
1152
1153        self.do_timing()
1154        self.print_timing()
1155        if with_timing:
1156            self.timer_step = 0
1157            self._v_timer_count += 1
1158            self._v_total += self.total_time
1159        return student_id
1160    ###)
1161
1162    security.declareProtected(ModifyPortalContent,'makeStudentLevel') ###(
1163    def makeStudentLevel(self,student_id):
1164        "create the StudyLevel for a returning Student"
1165        #import pdb;pdb.set_trace()
1166        logger = logging.getLogger('WAeUPTool.makeStudentLevel')
1167        students_folder = self.portal_url.getPortalObject().campus.students
1168        res = self.students_catalog(id=student_id)
1169        if res:
1170            st = res[0]
1171        course = st.course
1172        matric_no = st.matric_no
1173        level = st.level
1174        res = self.results_import(matric_no = matric_no)
1175        if res:
1176            results = res
1177        logger.info('%s creating Level %s' % (student_id,level))
1178        #
1179        # Level
1180        #
1181        student_obj = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1182        studycourse = getattr(student_obj,"study_course",None)
1183        self.portal_workflow.doActionFor(studycourse,'close_for_edit',dest_container=studycourse)
1184        l = getattr(studycourse,level,None)
1185        if l is None:
1186            studycourse.invokeFactory('StudentStudyLevel', level)
1187            l = getattr(studycourse, level)
1188            self.portal_workflow.doActionFor(l,'open',dest_container=l)
1189            l.getContent().edit(mapping={'Title': "Level %s" % level})
1190        ###)
1191       
1192       
1193    security.declareProtected(ModifyPortalContent,'makeStudentLevel') ###(
1194    def exportAllStudyLevels(self,student_id):
1195        "export the StudyLevels for a student"
1196        #import pdb;pdb.set_trace()
1197        logger = logging.getLogger('WAeUPTool.exportAllStudyLevels')
1198        students_folder = self.portal_url.getPortalObject().campus.students
1199        res = self.students_catalog(id=student_id)
1200        if res:
1201            st = res[0]
1202        course = st.course
1203        matric_no = st.matric_no
1204        level = st.level
1205        student_obj = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1206        studycourse = getattr(student_obj,"study_course",None)
1207        if studycourse:
1208            levels = studycourse.objectIds()
1209        else:
1210            levels = []
1211        stool = getToolByName(self, 'portal_schemas')
1212        schema = stool._getOb('student_study_level')
1213        fields = ['student_id','level']
1214        fields.extend(schema.keys())
1215        format = '"%(' + ')s","%('.join(fields) + ')s"'
1216        export_file = "%s/export/study_levels_removed.csv" % (i_home)
1217       
1218        if not os.path.exists(export_file): 
1219            file_handler = open(export_file,"a")
1220            headline = ','.join(fields)
1221            file_handler.write(headline +'\n')
1222        else:
1223            file_handler = open(export_file,"a")
1224       
1225        for level in levels:
1226            level_object = getattr(studycourse,level)
1227            level_content = level_object.getContent()
1228            d = {'student_id':student_id,'level':level}
1229            for field in schema.keys():
1230                d[field] = getattr(level_content,field,'')   
1231            line = format % d
1232            file_handler.write(line +'\n')               
1233           
1234        ###)       
1235
1236    security.declarePublic('getHallInfo') ###(
1237    def getHallInfo(self,bed):
1238        """return Hall Info"""
1239        info = {}
1240        bedsplit = bed.split('_')
1241        if len(bedsplit) == 4:
1242            hall,block,room,letter = bed.split('_')
1243        else:
1244            info['maintenance_code'] = 'None'
1245            return info
1246        res = ZCatalog.searchResults(self.portal_catalog_real,portal_type="AccoHall",id=hall)
1247        if res and len(res) == 1:
1248            hall_brain = res[0]
1249            hall_doc = hall_brain.getObject().getContent()
1250        else:
1251            return info
1252        info['hall_title'] = hall_brain.Title
1253        info['maintenance_code'] = hall_doc.maintenance_code
1254        res = ZCatalog.searchResults(self.portal_catalog_real,portal_type="ScratchCardBatch")
1255        batch_doc = None
1256        for brain in res:
1257            if brain.id.startswith(info['maintenance_code']):
1258                batch_doc = brain.getObject().getContent()
1259                break
1260        if batch_doc is None:
1261            info['maintenance_fee'] = ''
1262        else:
1263            info['maintenance_fee'] = batch_doc.cost
1264        return info
1265    ###)
1266
1267    security.declareProtected(ModifyPortalContent,'removePictureFolder') ###(
1268    def removePictureFolder(self,student_id):
1269        """remove picture_folder by renaming it"""
1270        picture_path = getImagesDir(student_id)
1271        dest_path = os.path.join("%s" % images_base,'removed',student_id)
1272        dest_path = dest_path + "_removed"
1273        if os.path.exists(dest_path) or not os.path.exists(picture_path):
1274            return False
1275        os.rename(picture_path,dest_path)
1276        return True
1277    ###)
1278
1279    security.declareProtected(ModifyPortalContent,'restorePictureFolder') ###(
1280    def restorePictureFolder(self,student_id):
1281        """restore picture_folder by renaming it"""
1282        picture_path = getImagesDir(student_id)
1283        orig_path = os.path.join("%s" % images_base,'removed',student_id)
1284        orig_path = orig_path + "_removed"
1285        if os.path.exists(picture_path) or not os.path.exists(orig_path):
1286            return False       
1287        os.rename(orig_path,picture_path)
1288        return True
1289    ###)
1290
1291    security.declarePublic('picturesExist') ###(
1292    def picturesExist(self, ids,student_id=None):
1293        """check if pictures exist in the filesystem"""
1294        if student_id is None:
1295            student_id = self.getStudentId()
1296        if student_id is None:
1297            return False
1298        picture_path = getImagesDir(student_id)
1299        #picture_path = os.path.join(images_base,student_id)
1300        if not os.path.exists(picture_path):
1301            return False
1302        pictures  = [picture[:picture.rfind('_')] for picture in os.listdir(picture_path)]
1303        return set(ids).issubset(set(pictures))
1304    ###)
1305   
1306        security.declarePublic('picturePathExists') ###(
1307    def picturePathExists(self, student_id=None):
1308        """check if picture path exists in the filesystem"""
1309        if student_id is None:
1310            student_id = self.getStudentId()
1311        if student_id is None:
1312            return False
1313        picture_path = getImagesDir(student_id)
1314        if os.path.exists(picture_path):
1315            return True
1316        return False
1317    ###)
1318   
1319   
1320    security.declareProtected(ModifyPortalContent,'removeUnusedImageFolders') ###(
1321    def removeUnusedImageFolders(self):
1322        """check if an unused image folders exists in the filesystem"""
1323        mtool = self.portal_membership
1324        member = mtool.getAuthenticatedMember()
1325        member_id = str(member)
1326        logger = logging.getLogger('WAeUPTool.removeUnusedImageFolders')
1327        abc = os.listdir(images_base)
1328        ifolders = []
1329        for i in abc:
1330            picture_path = os.path.join(images_base,i)
1331            ifolders.extend(os.listdir(picture_path))
1332        unused_ids = []
1333        for id in ifolders:
1334            res = self.students_catalog(id=id)
1335            if not res:
1336                unused_ids.append(id)
1337                #import pdb;pdb.set_trace()   
1338                if not id.endswith('removed'):
1339                    removed = self.waeup_tool.removePictureFolder(id) 
1340                    if removed:
1341                        logger.info('%s: image folder %s successfully removed' % (member_id,id))
1342                    else:
1343                        logger.info('%s: image folder %s could not be removed' % (member_id,id))
1344        return
1345       
1346    ###)   
1347
1348    security.declarePublic('picturesList') ###(
1349    def picturesList(self):
1350        """check if pictures exist in the filesystem"""
1351        path = 'images'
1352        student_id = self.getStudentId()
1353        #picture_path = os.path.join(i_home,path,student_id)
1354        picture_path = getImagesDir(student_id)
1355        if not os.path.exists(picture_path):
1356            return []
1357        return [picture[:picture.rfind('_')] for picture in os.listdir(picture_path)]
1358    ###)
1359
1360    security.declarePublic('showFsPicture') ###(
1361    def showFsPicture(self,path):
1362        """return a picture from the filesystem"""
1363        #picture_path = os.path.join(i_home,path)
1364        picture_path = os.path.join(images_base,path)
1365        response = self.REQUEST.RESPONSE
1366        #import pdb;pdb.set_trace()
1367        registry = getToolByName(self, 'mimetypes_registry')
1368        mimetype = str(registry.lookupExtension(path.lower()) or
1369                    registry.lookupExtension('file.bin'))
1370        if os.path.exists(picture_path):
1371            response.setHeader('Content-type',mimetype)
1372            return open(picture_path).read()
1373        picture_path = os.path.join(i_home,'import',path)
1374        if os.path.exists(picture_path):
1375            return open(picture_path).read()
1376    ###)
1377
1378    security.declareProtected(ModifyPortalContent,'deleteAllCourses') ###(
1379    def deleteAllCourses(self,department="All"):
1380        ''' delete the courses'''
1381        pm = self.portal_membership
1382        member = pm.getAuthenticatedMember()
1383
1384        if str(member) not in ("henrik","joachim"):
1385            return "not possible"
1386        if department == "All":
1387            res = self.portal_catalog({'meta_type': 'Department'})
1388        if len(res) < 1:
1389            return "No Departments found"
1390
1391        deleted = []
1392        for dep in res:
1393            cf = dep.getObject().courses
1394            if cf:
1395                cf.manage_delObjects(ids=cf.objectIds())
1396                deleted.append("deleted Courses in %s" % dep.getId)
1397        return "\r".join(deleted)
1398    ###)
1399
1400    security.declareProtected(ModifyPortalContent,'getLogfileLines') ###(
1401    def getLogfileLines(self,filename="event.log",numlines=20):
1402        """Get last NUMLINES lines of logfile FILENAME.
1403
1404        Return last lines' of a file in the instances logfile directory as
1405        a list. The number of returned lines equals `numlines' or less. If
1406        less than `numlines' lines are available, the whole file ist
1407        returned. If the file can not be opened or some other error
1408        occurs, empty list is returend.
1409        """
1410        result = []
1411        lines_hit = 0
1412
1413        # We only handle files in instances' log directory...
1414        logpath = os.path.join(i_home, "log")
1415        filename = str(os.path.abspath( os.path.join( logpath, filename )))
1416        if not filename.startswith( logpath ):
1417            # Attempt to access file outside log-dir...
1418            return []
1419
1420        try:
1421            fd = file( filename, "rb" )
1422        except IOError:
1423            return []
1424        if not fd:
1425            return []
1426
1427        if os.linesep == None:
1428            linesep = '\n'
1429        else:
1430            linesep = os.linesep
1431
1432        # Try to find 'numlines' times a lineseparator, searching from end
1433        # and moving to the beginning of file...
1434        fd.seek( 0, 2) # Move to end of file...
1435        while lines_hit < numlines:
1436            if fd.read(1) == linesep[-1]: # This moves filedescriptor
1437                                          # one step forward...
1438                lines_hit += 1
1439            try:
1440                fd.seek( -2, 1) # Go two bytes back from current pos...
1441            except IOError:
1442                # We cannot go back two bytes. Maybe the file is too small...
1443                break
1444        fd.seek(2,1)
1445
1446        # Read all lines from current position...
1447        result = fd.readlines()
1448        # Remove line endings...
1449        result = [x.strip() for x in result]
1450        fd.close()
1451        return result
1452    ###)
1453
1454    security.declareProtected(ModifyPortalContent,"getCallbacksFromLog")###(
1455    def getCallbacksFromLog(self,filename):
1456        """fix Online Payment Transactions from Z2.log entries"""
1457        import transaction
1458        import random
1459        from cgi import parse_qs
1460        from urlparse import urlparse
1461        #from pdb import set_trace
1462        wftool = self.portal_workflow
1463        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1464        students_folder = self.portal_url.getPortalObject().campus.students
1465        s = r'(?P<client_ip>\S+) - (?P<member_id>\S+) \['
1466        s += r'(?P<date>.*)\] "(?P<get>.*)" (?P<codes>\d+ \d+) "'
1467        s += r'(?P<intersw>.*)" "(?P<agent>.*)"'
1468        data = re.compile(s)
1469        start = True
1470        tr_count = 1
1471        total = 0
1472        #name = 'pume_results'
1473        #name = 'epaymentsuccessful_z2log2'
1474        name = filename
1475        no_import = []
1476        imported = []
1477        logger = logging.getLogger('WAeUPTool.getFailedTransactions')
1478        try:
1479            transactions = open("%s/import/%s" % (i_home,name),"rb").readlines()
1480        except:
1481            logger.error('Error reading %s' % name)
1482            return
1483        tas = []
1484        for line in transactions:
1485            dict = {}
1486            items = data.search(line)
1487            dict['idict'] = idict = items.groupdict()
1488            #print idict
1489            #from pdb import set_trace;set_trace()
1490            urlparsed = urlparse(idict['get'][4:])
1491            #print urlparsed
1492            path = urlparsed[2].split('/')
1493            dict['student_id'] = student_id = path[8]
1494            dict['payment_id'] = payment_id = path[10]
1495            dict['qs_dict'] = qs_dict = parse_qs(urlparsed[4])
1496            tas.append(dict)
1497            tr_count += 1
1498        return tas
1499    ###)
1500
1501    security.declareProtected(ModifyPortalContent,"importOnlinePaymentTransactions")###(
1502    def importOnlinePaymentTransactions(self):
1503        """load Online Payment Transactions from CSV values"""
1504        import transaction
1505        import random
1506        #from pdb import set_trace
1507        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1508        opt = self.online_payments_import
1509        students_folder = self.portal_url.getPortalObject().campus.students
1510        start = True
1511        tr_count = 1
1512        total = 0
1513        #name = 'pume_results'
1514        name = 'OnlineTransactions'
1515        no_import = []
1516        imported = []
1517        logger = logging.getLogger('WAeUPTool.importOnlinePaymentTransactions')
1518        try:
1519            transactions = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
1520        except:
1521            logger.error('Error reading %s.csv' % name)
1522            return
1523        for pay_transaction in transactions:
1524            if start:
1525                start = False
1526                logger.info('Start loading from %s.csv' % name)
1527                s = ','.join(['"%s"' % fn for fn in pay_transaction.keys()])
1528                no_import.append('%s,"Error"' % s)
1529                format = ','.join(['"%%(%s)s"' % fn for fn in pay_transaction.keys()])
1530                format_error = format + ',"%(Error)s"'
1531            data = {}
1532
1533            # format of the first file sent by Tayo
1534            #data['datetime'] = date = DateTime.DateTime(pay_transaction['Date'])
1535            #data['student_id'] = student_id = pay_transaction['Payer ID']
1536            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
1537            #data['response_code'] = response_code = pay_transaction['Resp Code']
1538            #data['amount'] = amount = pay_transaction['Amount']
1539
1540            # format of the second file sent by Tayo
1541            #data['datetime'] = date = 0
1542            #data['student_id'] = student_id = pay_transaction['Payer ID']
1543            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
1544            #data['response_code'] = response_code = '00'
1545            #data['amount'] = amount = pay_transaction['Amount']
1546
1547            # format of the third file sent by Kehinde
1548            data['datetime'] = date = 0
1549            data['student_id'] = student_id = pay_transaction['customer_id']
1550            data['order_id'] = order_id = pay_transaction['merchant_reference']
1551            data['response_code'] = response_code = '00'
1552            data['amount'] = amount = pay_transaction['Amount']
1553
1554            dup = False
1555            if response_code == "12":
1556                continue
1557            try:
1558                opt.addRecord(**data)
1559            except ValueError:
1560                dup = True
1561            #from pdb import set_trace;set_trace()
1562            if dup:
1563                if response_code == "00":
1564                    try:
1565                        opt.modifyRecord(**data)
1566                    except:
1567                        logger.info("duplicate uid, order_id %(order_id)s, student_id %(student_id)s, response_code %(response_code)s" % data)
1568                        continue
1569                else:
1570                    pay_transaction['Error'] = "Duplicate order_id"
1571                    no_import.append( format_error % pay_transaction)
1572                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
1573                    continue
1574            tr_count += 1
1575            if tr_count > 1000:
1576                if len(no_import) > 0:
1577                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1578                             '\n'.join(no_import) + '\n')
1579                    no_import = []
1580                em = '%d transactions committed\n' % (tr_count)
1581                transaction.commit()
1582                regs = []
1583                logger.info(em)
1584                total += tr_count
1585                tr_count = 0
1586        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1587                                                '\n'.join(no_import))
1588        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
1589    ###)
1590
1591    security.declareProtected(ModifyPortalContent,"importData")###(
1592    def importData(self,filename,name,edit=False,bypass_queue_catalog=False):
1593        """load data from CSV values"""
1594        import transaction
1595        import random
1596        students_folder = self.portal_url.getPortalObject().campus.students
1597        uploads_folder = self.portal_url.getPortalObject().campus.uploads
1598        pending_only = False
1599        pend_str = '--'
1600        elapse = time.time()
1601        #
1602        # preparations
1603        #
1604        if filename == pend_str:
1605            pending_only = True
1606        importer_name = ''.join([part.capitalize() for part in name.split('_')])
1607        importer = eval("%sImport" % importer_name)(self)
1608        logger = importer.logger
1609        if importer.init_errors:
1610            logger.info(importer.init_errors)
1611            return importer.init_errors
1612        member = importer.member
1613        #current = importer.current
1614        import_date = importer.import_date
1615        #
1616        # not_imported
1617        #
1618        info = importer.info
1619        data_keys = importer.data_keys
1620        csv_keys = importer.csv_keys
1621        #csv_keys.extend(info.keys())
1622        headline_mapping = dict((k,k) for k in csv_keys)
1623        #
1624        # pending
1625        #
1626        pending_path = importer.pending_path
1627        pending_tmp = importer.pending_tmp
1628        pending_backup = importer.pending_backup
1629        pending_fn = importer.pending_fn
1630        imported_path = importer.imported_path
1631        imported_fn = importer.imported_fn
1632        commit_after = importer.commit_after
1633        pending = []
1634        pending_digests = []
1635        #total_added_to_pending = 0
1636        if not pending_only:
1637            pending,pending_digests = importer.makeIdLists()
1638            pending_at_start = len(pending)
1639        datafile = open(pending_tmp,"w")
1640        pending_csv_writer = csv.DictWriter(datafile,
1641                                                    csv_keys,
1642                                                    extrasaction='ignore')
1643        pending_csv_writer.writerow(headline_mapping)
1644        datafile.close()
1645        #
1646        # imported
1647        #
1648        if not os.path.exists(imported_path):
1649            datafile = open(imported_path,"w")
1650            imported_csv_writer = csv.DictWriter(datafile,
1651                                                 csv_keys,
1652                                                 extrasaction='ignore')
1653            imported_csv_writer.writerow(headline_mapping)
1654            datafile.close()
1655        start = True
1656        tr_count = 0
1657        total = 0
1658        total_added_to_imported = 0
1659        total_pending = 0
1660        import_source_done = ""
1661        if pending_only:
1662            import_source_path = pending_path
1663        else:
1664            import_source_path = "%s/import/%s.csv" % (i_home,filename)
1665            import_source_done = "%s/import/%s.done" % (i_home,filename)
1666        if not os.path.exists(import_source_path):
1667            fn = os.path.split(import_source_path)[1]
1668            em = 'no import file %(fn)s' % vars()
1669            return em
1670        import_source_fn = os.path.split(import_source_path)[1]
1671        if not pending_only:
1672            info['imported_from'] = import_source_fn
1673        headline = csv.reader(open(import_source_path,"rb")).next()
1674        if "import_mode" not in headline:
1675            msg = 'import_mode must be in heading'
1676            return msg
1677        invalid_keys = importer.checkHeadline(headline)
1678        if invalid_keys:
1679            return 'not ignorable key(s): "%s" found in heading' % ", ".join(invalid_keys)
1680
1681        import_keys = [k.strip() for k in headline if not (k.strip().startswith('ignore')
1682                                                         or k.strip() in info.keys())]
1683        # diff2schema = set(import_keys).difference(set(importer.schema.keys()))
1684        # diff2layout = set(import_keys).difference(set(importer.layout.keys()))
1685        # if diff2schema and diff2schema != set(['id',]):
1686        #     msg = 'not ignorable key(s): "%s" found in heading' % ", ".join(diff2schema)
1687        #     return msg
1688        #
1689        # start importing
1690        #
1691        try:
1692            reader = csv.DictReader(open(import_source_path,"rb"))
1693        except:
1694            msg = 'Error reading %s.csv' % filename
1695            logger.error(msg)
1696            return msg
1697        items = [item for item in reader]
1698        total_to_import = len(items)
1699        tti_float = float(total_to_import)
1700        if pending_only:
1701            pending_at_start = total_to_import
1702        count = 0
1703        imported = []
1704        old_commit_count = 0
1705        error_count = imported_count = 0
1706        already_in = 0
1707        for record in items:
1708            item = {}
1709            empty_value_keys = []
1710            for k,v in record.items():
1711                if k is None:
1712                    continue
1713                if v:
1714                    if v == EMPTY:
1715                        empty_value_keys += k,
1716                        v = ''
1717                    item[k.strip()] = v.strip()
1718            count += 1
1719            if start:
1720                start = False
1721                adapters = [MappingStorageAdapter(importer.schema, item)]
1722                logger.info('%(member)s starts import from %(import_source_fn)s' % vars())
1723            dm = DataModel(item, adapters,context=self)
1724            ds = DataStructure(data=item,datamodel=dm)
1725            error_string = ""
1726            total += 1
1727            import_mode = item.get('import_mode','')
1728            import_method = getattr(importer, '%(import_mode)s' % vars(),None )
1729            if import_method is None:
1730                error_string += "import_mode '%(import_mode)s' is invalid" % vars()
1731            elif (import_mode in importer.required_modes and
1732                not set(importer.required_keys[import_mode]).issubset(set(item.keys()))):
1733                diff2import = set(importer.required_keys[import_mode]).difference(set(item.keys()))
1734                error_string += 'required key(s): "%s" not found in record' % ", ".join(diff2import)
1735            else:
1736                for k in import_keys:
1737                    if k not in item.keys() or k not in importer.validators.keys():
1738                        continue
1739                    if not importer.validators[k](ds,mode=import_mode):
1740                        error_string += ' ++ '
1741                        error_string += "%s: %s" % (k,self.translation_service(ds.getError(k),
1742                                                                           ds.getErrorMapping(k)))
1743            if error_string:
1744                error = error_string
1745                id = ''
1746                mapping = item
1747            else:
1748                temp_item = item.copy()
1749                temp_item.update(dm)
1750                results = import_method(temp_item)
1751                id = results[0]
1752                error = results[1]
1753                mapping = results[2]
1754            #
1755            # restore some values
1756            #
1757            for k in empty_value_keys:
1758                mapping[k] = EMPTY
1759            if mapping.has_key('sex'):
1760                #import pdb;pdb.set_trace()
1761                if mapping['sex'] == True:
1762                    mapping['sex'] = 'F'
1763                elif mapping['sex'] == False:
1764                    mapping['sex'] = 'M'
1765            if pending_only:
1766                info['imported_from'] = item['imported_from']
1767            data_string = ", ".join("%s: %s" % (k,v) for k,v in mapping.items())
1768            info['error'] = error
1769            info['import_record_no'] = count + 1
1770            mapping.update(info)
1771            log_list = []
1772            if error:
1773                error_count += 1
1774                digest = makeDigest(mapping,data_keys)
1775                if digest not in pending_digests:
1776                    pending_digests += digest,
1777                    pending.append(mapping)
1778                    if not pending_only:
1779                        log_list += "record from %(import_source_fn)s added to %(pending_fn)s, %(data_string)s, %(error)s" % vars(),
1780                else:
1781                    already_in += 1
1782                    pass
1783            else:
1784                imported_count += 1
1785                imported += mapping,
1786                log_list += "record imported and added to %(imported_fn)s from %(import_source_fn)s, %(data_string)s" % vars(),
1787            if log_list:
1788                time_till_now = time.time() - elapse
1789                percent_finished = (error_count + imported_count)/tti_float*100
1790                log_list.insert(0,("%(percent_finished)6.3f %% done in %(time_till_now)3.2fs," % vars()),)
1791                logger.info(' '.join(log_list))
1792            finished = count > total_to_import - 1
1793            must_commit = (imported_count != old_commit_count) and (not imported_count % commit_after)
1794            if must_commit:
1795                old_commit_count = imported_count
1796
1797            if must_commit or finished:
1798                if len(imported):
1799                    transaction.commit()
1800                    datafile = open(imported_path,"a")
1801                    writer = csv.DictWriter(datafile,
1802                                            csv_keys,
1803                                            extrasaction='ignore')
1804                    writer.writerows(imported)
1805                    datafile.close()
1806                    total_added_to_imported += len(imported)
1807                    imported = []
1808                if len(pending) > 0:
1809                    datafile = open(pending_tmp,"a")
1810                    writer = csv.DictWriter(datafile,
1811                                            csv_keys,
1812                                            extrasaction='ignore')
1813                    writer.writerows(pending)
1814                    datafile.close()
1815                    total_pending += len(pending)
1816                    #total_added_to_pending += len(pending)
1817                    pending = []
1818                if not finished:
1819                    msg = '%(commit_after)d records imported and committed of total %(total_added_to_imported)d\n' % vars()
1820                    logger.info(msg)
1821        elapse = time.time() - elapse
1822        if os.path.exists(pending_path):
1823            copy2(pending_path,pending_backup)
1824        copy2(pending_tmp,pending_path)
1825        msg = "finished importing from %(import_source_fn)s in %(elapse).2f seconds, " % vars()
1826        msg += "%(count)d records totally read, %(total_added_to_imported)d added to %(imported_fn)s, " % vars()
1827        if pending_only:
1828            removed_pending = pending_at_start - total_pending
1829            msg += "%(removed_pending)d removed from %(pending_fn)s" % vars()
1830        else:
1831            added_pending = total_pending - pending_at_start
1832            msg += "%(added_pending)d added to %(pending_fn)s, %(already_in)s already in %(pending_fn)s" % vars()
1833        #msg += "%(total_pending)d totally written" % vars()    # this line does not make any sense
1834        logger.info(msg)
1835        if import_source_done:
1836            copy(import_source_path,import_source_done)
1837            os.remove(import_source_path)
1838            upload = getattr(uploads_folder,os.path.split(import_source_path)[1],None)
1839            if upload is not None:
1840                upload_doc = upload.getContent()
1841                mapping = {}
1842                #mapping['import_date'] = DateTime.DateTime()
1843                mapping['import_date'] = import_date
1844                mapping['imported_by'] = importer.imported_by
1845                mapping['import_message'] = msg
1846                upload_doc.edit(mapping = mapping)
1847        os.remove(pending_tmp)
1848        return msg
1849    ###)
1850
1851    security.declareProtected(ModifyPortalContent,"moveImagesToFS")###(
1852    def moveImagesToFS(self,student_id="O738726"):
1853        "move the images to the filesystem"
1854        images_dir = getImagesDir(student_id)
1855        #images_dir = os.path.join("%s" % images_base,student_id)
1856        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1857        stool = getToolByName(self, 'portal_schemas')
1858        schemas = ['student_application',
1859                   'student_clearance',
1860                   ]
1861        created = False
1862        for schema_id in schemas:
1863            schema = stool._getOb(schema_id)
1864            object = getattr(student_folder,schema_id[len('student_'):],None)
1865            if object is None:
1866                continue
1867            doc = object.getContent()
1868            for key in schema.keys():
1869                if schema[key].meta_type != "CPS Image Field":
1870                    continue
1871                #import pdb;pdb.set_trace()
1872                image = getattr(doc,key,None)
1873                if not image or not hasattr(image,"data"):
1874                    continue
1875                if not created:
1876                    if not os.path.exists(images_dir):
1877                        os.mkdir(images_dir)
1878                    created = True
1879                filename = os.path.join(images_dir,"%(key)s_%(student_id)s.jpg" % vars())
1880                open(filename,"wb").write(str(image.data))
1881    ###)
1882
1883    security.declareProtected(ModifyPortalContent,"movePassportToFS")###(
1884    def movePassportToFS(self,student_id="O738726"):
1885        "move the passports to the filesystem"
1886        images_dir = os.path.join("%s" % i_home,'passports')
1887        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1888        stool = getToolByName(self, 'portal_schemas')
1889        schemas = ['student_application',
1890                   #'student_clearance',
1891                   ]
1892        created = False
1893        for schema_id in schemas:
1894            schema = stool._getOb(schema_id)
1895            object = getattr(student_folder,schema_id[len('student_'):],None)
1896            if object is None:
1897                continue
1898            doc = object.getContent()
1899            for key in schema.keys():
1900                if schema[key].meta_type != "CPS Image Field":
1901                    continue
1902                #import pdb;pdb.set_trace()
1903                image = getattr(doc,key)
1904                if not hasattr(image,"data"):
1905                    continue
1906                if not created:
1907                    if not os.path.exists(images_dir):
1908                        os.mkdir(images_dir)
1909                    created = True
1910                filename = os.path.join(images_dir,"%(student_id)s.jpg" % vars())
1911                open(filename,"wb").write(str(image.data))
1912    ###)
1913   
1914   
1915    security.declarePublic('getConfigParams')
1916    def getConfigParams(self,conf_id="configuration"):
1917        conf = getattr(self.portal_url.getPortalObject().campus,conf_id)
1918        conf_obj = conf.getContent()
1919        stool = getToolByName(self, 'portal_schemas')
1920        schema = stool._getOb('configuration')
1921        d = {}
1922        for key in schema.keys():
1923            d[key] = getattr(conf_obj,key,None)
1924        return d
1925
1926
1927InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.