source: WAeUP_SRP/trunk/WAeUPTool.py @ 5174

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

accommodation_edit_form.pt: fix ul

WAeUPTool.py: insert comment

  • Property svn:keywords set to Id
File size: 77.9 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 5168 2010-04-26 08:52: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        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        # Pick the first pin batch which the right prefix. This may cause problems if old maintenance fee batches exist.
1259        # They must be removed first. 
1260        for brain in res:
1261            if brain.id.startswith(info['maintenance_code']):
1262                batch_doc = brain.getObject().getContent()
1263                break
1264        if batch_doc is None:
1265            info['maintenance_fee'] = ''
1266        else:
1267            info['maintenance_fee'] = batch_doc.cost
1268        return info
1269    ###)
1270
1271    security.declareProtected(ModifyPortalContent,'removePictureFolder') ###(
1272    def removePictureFolder(self,student_id):
1273        """remove picture_folder by renaming it"""
1274        picture_path = getImagesDir(student_id)
1275        dest_path = os.path.join("%s" % images_base,'removed',student_id)
1276        dest_path = dest_path + "_removed"
1277        if os.path.exists(dest_path) or not os.path.exists(picture_path):
1278            return False
1279        os.rename(picture_path,dest_path)
1280        return True
1281    ###)
1282
1283    security.declareProtected(ModifyPortalContent,'restorePictureFolder') ###(
1284    def restorePictureFolder(self,student_id):
1285        """restore picture_folder by renaming it"""
1286        picture_path = getImagesDir(student_id)
1287        orig_path = os.path.join("%s" % images_base,'removed',student_id)
1288        orig_path = orig_path + "_removed"
1289        if os.path.exists(picture_path) or not os.path.exists(orig_path):
1290            return False       
1291        os.rename(orig_path,picture_path)
1292        return True
1293    ###)
1294
1295    security.declarePublic('picturesExist') ###(
1296    def picturesExist(self, ids,student_id=None):
1297        """check if pictures exist in the filesystem"""
1298        if student_id is None:
1299            student_id = self.getStudentId()
1300        if student_id is None:
1301            return False
1302        picture_path = getImagesDir(student_id)
1303        #picture_path = os.path.join(images_base,student_id)
1304        if not os.path.exists(picture_path):
1305            return False
1306        pictures  = [picture[:picture.rfind('_')] for picture in os.listdir(picture_path)]
1307        return set(ids).issubset(set(pictures))
1308    ###)
1309   
1310        security.declarePublic('picturePathExists') ###(
1311    def picturePathExists(self, student_id=None):
1312        """check if picture path exists in the filesystem"""
1313        if student_id is None:
1314            student_id = self.getStudentId()
1315        if student_id is None:
1316            return False
1317        picture_path = getImagesDir(student_id)
1318        if os.path.exists(picture_path):
1319            return True
1320        return False
1321    ###)
1322   
1323   
1324    security.declareProtected(ModifyPortalContent,'removeUnusedImageFolders') ###(
1325    def removeUnusedImageFolders(self):
1326        """check if an unused image folders exists in the filesystem"""
1327        mtool = self.portal_membership
1328        member = mtool.getAuthenticatedMember()
1329        member_id = str(member)
1330        logger = logging.getLogger('WAeUPTool.removeUnusedImageFolders')
1331        abc = os.listdir(images_base)
1332        ifolders = []
1333        for i in abc:
1334            picture_path = os.path.join(images_base,i)
1335            ifolders.extend(os.listdir(picture_path))
1336        unused_ids = []
1337        for id in ifolders:
1338            res = self.students_catalog(id=id)
1339            if not res:
1340                unused_ids.append(id)
1341                #import pdb;pdb.set_trace()   
1342                if not id.endswith('removed'):
1343                    removed = self.waeup_tool.removePictureFolder(id) 
1344                    if removed:
1345                        logger.info('%s: image folder %s successfully removed' % (member_id,id))
1346                    else:
1347                        logger.info('%s: image folder %s could not be removed' % (member_id,id))
1348        return
1349       
1350    ###)   
1351
1352    security.declarePublic('picturesList') ###(
1353    def picturesList(self):
1354        """check if pictures exist in the filesystem"""
1355        path = 'images'
1356        student_id = self.getStudentId()
1357        #picture_path = os.path.join(i_home,path,student_id)
1358        picture_path = getImagesDir(student_id)
1359        if not os.path.exists(picture_path):
1360            return []
1361        return [picture[:picture.rfind('_')] for picture in os.listdir(picture_path)]
1362    ###)
1363
1364    security.declarePublic('showFsPicture') ###(
1365    def showFsPicture(self,path):
1366        """return a picture from the filesystem"""
1367        #picture_path = os.path.join(i_home,path)
1368        picture_path = os.path.join(images_base,path)
1369        response = self.REQUEST.RESPONSE
1370        #import pdb;pdb.set_trace()
1371        registry = getToolByName(self, 'mimetypes_registry')
1372        mimetype = str(registry.lookupExtension(path.lower()) or
1373                    registry.lookupExtension('file.bin'))
1374        if os.path.exists(picture_path):
1375            response.setHeader('Content-type',mimetype)
1376            return open(picture_path).read()
1377        picture_path = os.path.join(i_home,'import',path)
1378        if os.path.exists(picture_path):
1379            return open(picture_path).read()
1380    ###)
1381
1382    security.declareProtected(ModifyPortalContent,'deleteAllCourses') ###(
1383    def deleteAllCourses(self,department="All"):
1384        ''' delete the courses'''
1385        pm = self.portal_membership
1386        member = pm.getAuthenticatedMember()
1387
1388        if str(member) not in ("henrik","joachim"):
1389            return "not possible"
1390        if department == "All":
1391            res = self.portal_catalog({'meta_type': 'Department'})
1392        if len(res) < 1:
1393            return "No Departments found"
1394
1395        deleted = []
1396        for dep in res:
1397            cf = dep.getObject().courses
1398            if cf:
1399                cf.manage_delObjects(ids=cf.objectIds())
1400                deleted.append("deleted Courses in %s" % dep.getId)
1401        return "\r".join(deleted)
1402    ###)
1403
1404    security.declareProtected(ModifyPortalContent,'getLogfileLines') ###(
1405    def getLogfileLines(self,filename="event.log",numlines=20):
1406        """Get last NUMLINES lines of logfile FILENAME.
1407
1408        Return last lines' of a file in the instances logfile directory as
1409        a list. The number of returned lines equals `numlines' or less. If
1410        less than `numlines' lines are available, the whole file ist
1411        returned. If the file can not be opened or some other error
1412        occurs, empty list is returend.
1413        """
1414        result = []
1415        lines_hit = 0
1416
1417        # We only handle files in instances' log directory...
1418        logpath = os.path.join(i_home, "log")
1419        filename = str(os.path.abspath( os.path.join( logpath, filename )))
1420        if not filename.startswith( logpath ):
1421            # Attempt to access file outside log-dir...
1422            return []
1423
1424        try:
1425            fd = file( filename, "rb" )
1426        except IOError:
1427            return []
1428        if not fd:
1429            return []
1430
1431        if os.linesep == None:
1432            linesep = '\n'
1433        else:
1434            linesep = os.linesep
1435
1436        # Try to find 'numlines' times a lineseparator, searching from end
1437        # and moving to the beginning of file...
1438        fd.seek( 0, 2) # Move to end of file...
1439        while lines_hit < numlines:
1440            if fd.read(1) == linesep[-1]: # This moves filedescriptor
1441                                          # one step forward...
1442                lines_hit += 1
1443            try:
1444                fd.seek( -2, 1) # Go two bytes back from current pos...
1445            except IOError:
1446                # We cannot go back two bytes. Maybe the file is too small...
1447                break
1448        fd.seek(2,1)
1449
1450        # Read all lines from current position...
1451        result = fd.readlines()
1452        # Remove line endings...
1453        result = [x.strip() for x in result]
1454        fd.close()
1455        return result
1456    ###)
1457
1458    security.declareProtected(ModifyPortalContent,"getCallbacksFromLog")###(
1459    def getCallbacksFromLog(self,filename):
1460        """fix Online Payment Transactions from Z2.log entries"""
1461        import transaction
1462        import random
1463        from cgi import parse_qs
1464        from urlparse import urlparse
1465        #from pdb import set_trace
1466        wftool = self.portal_workflow
1467        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1468        students_folder = self.portal_url.getPortalObject().campus.students
1469        s = r'(?P<client_ip>\S+) - (?P<member_id>\S+) \['
1470        s += r'(?P<date>.*)\] "(?P<get>.*)" (?P<codes>\d+ \d+) "'
1471        s += r'(?P<intersw>.*)" "(?P<agent>.*)"'
1472        data = re.compile(s)
1473        start = True
1474        tr_count = 1
1475        total = 0
1476        #name = 'pume_results'
1477        #name = 'epaymentsuccessful_z2log2'
1478        name = filename
1479        no_import = []
1480        imported = []
1481        logger = logging.getLogger('WAeUPTool.getFailedTransactions')
1482        try:
1483            transactions = open("%s/import/%s" % (i_home,name),"rb").readlines()
1484        except:
1485            logger.error('Error reading %s' % name)
1486            return
1487        tas = []
1488        for line in transactions:
1489            dict = {}
1490            items = data.search(line)
1491            dict['idict'] = idict = items.groupdict()
1492            #print idict
1493            #from pdb import set_trace;set_trace()
1494            urlparsed = urlparse(idict['get'][4:])
1495            #print urlparsed
1496            path = urlparsed[2].split('/')
1497            dict['student_id'] = student_id = path[8]
1498            dict['payment_id'] = payment_id = path[10]
1499            dict['qs_dict'] = qs_dict = parse_qs(urlparsed[4])
1500            tas.append(dict)
1501            tr_count += 1
1502        return tas
1503    ###)
1504
1505    security.declareProtected(ModifyPortalContent,"importOnlinePaymentTransactions")###(
1506    def importOnlinePaymentTransactions(self):
1507        """load Online Payment Transactions from CSV values"""
1508        import transaction
1509        import random
1510        #from pdb import set_trace
1511        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1512        opt = self.online_payments_import
1513        students_folder = self.portal_url.getPortalObject().campus.students
1514        start = True
1515        tr_count = 1
1516        total = 0
1517        #name = 'pume_results'
1518        name = 'OnlineTransactions'
1519        no_import = []
1520        imported = []
1521        logger = logging.getLogger('WAeUPTool.importOnlinePaymentTransactions')
1522        try:
1523            transactions = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
1524        except:
1525            logger.error('Error reading %s.csv' % name)
1526            return
1527        for pay_transaction in transactions:
1528            if start:
1529                start = False
1530                logger.info('Start loading from %s.csv' % name)
1531                s = ','.join(['"%s"' % fn for fn in pay_transaction.keys()])
1532                no_import.append('%s,"Error"' % s)
1533                format = ','.join(['"%%(%s)s"' % fn for fn in pay_transaction.keys()])
1534                format_error = format + ',"%(Error)s"'
1535            data = {}
1536
1537            # format of the first file sent by Tayo
1538            #data['datetime'] = date = DateTime.DateTime(pay_transaction['Date'])
1539            #data['student_id'] = student_id = pay_transaction['Payer ID']
1540            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
1541            #data['response_code'] = response_code = pay_transaction['Resp Code']
1542            #data['amount'] = amount = pay_transaction['Amount']
1543
1544            # format of the second file sent by Tayo
1545            #data['datetime'] = date = 0
1546            #data['student_id'] = student_id = pay_transaction['Payer ID']
1547            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
1548            #data['response_code'] = response_code = '00'
1549            #data['amount'] = amount = pay_transaction['Amount']
1550
1551            # format of the third file sent by Kehinde
1552            data['datetime'] = date = 0
1553            data['student_id'] = student_id = pay_transaction['customer_id']
1554            data['order_id'] = order_id = pay_transaction['merchant_reference']
1555            data['response_code'] = response_code = '00'
1556            data['amount'] = amount = pay_transaction['Amount']
1557
1558            dup = False
1559            if response_code == "12":
1560                continue
1561            try:
1562                opt.addRecord(**data)
1563            except ValueError:
1564                dup = True
1565            #from pdb import set_trace;set_trace()
1566            if dup:
1567                if response_code == "00":
1568                    try:
1569                        opt.modifyRecord(**data)
1570                    except:
1571                        logger.info("duplicate uid, order_id %(order_id)s, student_id %(student_id)s, response_code %(response_code)s" % data)
1572                        continue
1573                else:
1574                    pay_transaction['Error'] = "Duplicate order_id"
1575                    no_import.append( format_error % pay_transaction)
1576                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
1577                    continue
1578            tr_count += 1
1579            if tr_count > 1000:
1580                if len(no_import) > 0:
1581                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1582                             '\n'.join(no_import) + '\n')
1583                    no_import = []
1584                em = '%d transactions committed\n' % (tr_count)
1585                transaction.commit()
1586                regs = []
1587                logger.info(em)
1588                total += tr_count
1589                tr_count = 0
1590        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1591                                                '\n'.join(no_import))
1592        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
1593    ###)
1594
1595    security.declareProtected(ModifyPortalContent,"importData")###(
1596    def importData(self,filename,name,edit=False,bypass_queue_catalog=False):
1597        """load data from CSV values"""
1598        import transaction
1599        import random
1600        students_folder = self.portal_url.getPortalObject().campus.students
1601        uploads_folder = self.portal_url.getPortalObject().campus.uploads
1602        pending_only = False
1603        pend_str = '--'
1604        elapse = time.time()
1605        #
1606        # preparations
1607        #
1608        if filename == pend_str:
1609            pending_only = True
1610        importer_name = ''.join([part.capitalize() for part in name.split('_')])
1611        importer = eval("%sImport" % importer_name)(self)
1612        logger = importer.logger
1613        if importer.init_errors:
1614            logger.info(importer.init_errors)
1615            return importer.init_errors
1616        member = importer.member
1617        #current = importer.current
1618        import_date = importer.import_date
1619        #
1620        # not_imported
1621        #
1622        info = importer.info
1623        data_keys = importer.data_keys
1624        csv_keys = importer.csv_keys
1625        #csv_keys.extend(info.keys())
1626        headline_mapping = dict((k,k) for k in csv_keys)
1627        #
1628        # pending
1629        #
1630        pending_path = importer.pending_path
1631        pending_tmp = importer.pending_tmp
1632        pending_backup = importer.pending_backup
1633        pending_fn = importer.pending_fn
1634        imported_path = importer.imported_path
1635        imported_fn = importer.imported_fn
1636        commit_after = importer.commit_after
1637        pending = []
1638        pending_digests = []
1639        #total_added_to_pending = 0
1640        if not pending_only:
1641            pending,pending_digests = importer.makeIdLists()
1642            pending_at_start = len(pending)
1643        datafile = open(pending_tmp,"w")
1644        pending_csv_writer = csv.DictWriter(datafile,
1645                                                    csv_keys,
1646                                                    extrasaction='ignore')
1647        pending_csv_writer.writerow(headline_mapping)
1648        datafile.close()
1649        #
1650        # imported
1651        #
1652        if not os.path.exists(imported_path):
1653            datafile = open(imported_path,"w")
1654            imported_csv_writer = csv.DictWriter(datafile,
1655                                                 csv_keys,
1656                                                 extrasaction='ignore')
1657            imported_csv_writer.writerow(headline_mapping)
1658            datafile.close()
1659        start = True
1660        tr_count = 0
1661        total = 0
1662        total_added_to_imported = 0
1663        total_pending = 0
1664        import_source_done = ""
1665        if pending_only:
1666            import_source_path = pending_path
1667        else:
1668            import_source_path = "%s/import/%s.csv" % (i_home,filename)
1669            import_source_done = "%s/import/%s.done" % (i_home,filename)
1670        if not os.path.exists(import_source_path):
1671            fn = os.path.split(import_source_path)[1]
1672            em = 'no import file %(fn)s' % vars()
1673            return em
1674        import_source_fn = os.path.split(import_source_path)[1]
1675        if not pending_only:
1676            info['imported_from'] = import_source_fn
1677        headline = csv.reader(open(import_source_path,"rb")).next()
1678        if "import_mode" not in headline:
1679            msg = 'import_mode must be in heading'
1680            return msg
1681        invalid_keys = importer.checkHeadline(headline)
1682        if invalid_keys:
1683            return 'not ignorable key(s): "%s" found in heading' % ", ".join(invalid_keys)
1684
1685        import_keys = [k.strip() for k in headline if not (k.strip().startswith('ignore')
1686                                                         or k.strip() in info.keys())]
1687        # diff2schema = set(import_keys).difference(set(importer.schema.keys()))
1688        # diff2layout = set(import_keys).difference(set(importer.layout.keys()))
1689        # if diff2schema and diff2schema != set(['id',]):
1690        #     msg = 'not ignorable key(s): "%s" found in heading' % ", ".join(diff2schema)
1691        #     return msg
1692        #
1693        # start importing
1694        #
1695        try:
1696            reader = csv.DictReader(open(import_source_path,"rb"))
1697        except:
1698            msg = 'Error reading %s.csv' % filename
1699            logger.error(msg)
1700            return msg
1701        items = [item for item in reader]
1702        total_to_import = len(items)
1703        tti_float = float(total_to_import)
1704        if pending_only:
1705            pending_at_start = total_to_import
1706        count = 0
1707        imported = []
1708        old_commit_count = 0
1709        error_count = imported_count = 0
1710        already_in = 0
1711        for record in items:
1712            item = {}
1713            empty_value_keys = []
1714            for k,v in record.items():
1715                if k is None:
1716                    continue
1717                if v:
1718                    if v == EMPTY:
1719                        empty_value_keys += k,
1720                        v = ''
1721                    item[k.strip()] = v.strip()
1722            count += 1
1723            if start:
1724                start = False
1725                adapters = [MappingStorageAdapter(importer.schema, item)]
1726                logger.info('%(member)s starts import from %(import_source_fn)s' % vars())
1727            dm = DataModel(item, adapters,context=self)
1728            ds = DataStructure(data=item,datamodel=dm)
1729            error_string = ""
1730            total += 1
1731            import_mode = item.get('import_mode','')
1732            import_method = getattr(importer, '%(import_mode)s' % vars(),None )
1733            if import_method is None:
1734                error_string += "import_mode '%(import_mode)s' is invalid" % vars()
1735            elif (import_mode in importer.required_modes and
1736                not set(importer.required_keys[import_mode]).issubset(set(item.keys()))):
1737                diff2import = set(importer.required_keys[import_mode]).difference(set(item.keys()))
1738                error_string += 'required key(s): "%s" not found in record' % ", ".join(diff2import)
1739            else:
1740                for k in import_keys:
1741                    if k not in item.keys() or k not in importer.validators.keys():
1742                        continue
1743                    if not importer.validators[k](ds,mode=import_mode):
1744                        error_string += ' ++ '
1745                        error_string += "%s: %s" % (k,self.translation_service(ds.getError(k),
1746                                                                           ds.getErrorMapping(k)))
1747            if error_string:
1748                error = error_string
1749                id = ''
1750                mapping = item
1751            else:
1752                temp_item = item.copy()
1753                temp_item.update(dm)
1754                results = import_method(temp_item)
1755                id = results[0]
1756                error = results[1]
1757                mapping = results[2]
1758            #
1759            # restore some values
1760            #
1761            for k in empty_value_keys:
1762                mapping[k] = EMPTY
1763            if mapping.has_key('sex'):
1764                #import pdb;pdb.set_trace()
1765                if mapping['sex'] == True:
1766                    mapping['sex'] = 'F'
1767                elif mapping['sex'] == False:
1768                    mapping['sex'] = 'M'
1769            if pending_only:
1770                info['imported_from'] = item['imported_from']
1771            data_string = ", ".join("%s: %s" % (k,v) for k,v in mapping.items())
1772            info['error'] = error
1773            info['import_record_no'] = count + 1
1774            mapping.update(info)
1775            log_list = []
1776            if error:
1777                error_count += 1
1778                digest = makeDigest(mapping,data_keys)
1779                if digest not in pending_digests:
1780                    pending_digests += digest,
1781                    pending.append(mapping)
1782                    if not pending_only:
1783                        log_list += "record from %(import_source_fn)s added to %(pending_fn)s, %(data_string)s, %(error)s" % vars(),
1784                else:
1785                    already_in += 1
1786                    pass
1787            else:
1788                imported_count += 1
1789                imported += mapping,
1790                log_list += "record imported and added to %(imported_fn)s from %(import_source_fn)s, %(data_string)s" % vars(),
1791            if log_list:
1792                time_till_now = time.time() - elapse
1793                percent_finished = (error_count + imported_count)/tti_float*100
1794                log_list.insert(0,("%(percent_finished)6.3f %% done in %(time_till_now)3.2fs," % vars()),)
1795                logger.info(' '.join(log_list))
1796            finished = count > total_to_import - 1
1797            must_commit = (imported_count != old_commit_count) and (not imported_count % commit_after)
1798            if must_commit:
1799                old_commit_count = imported_count
1800
1801            if must_commit or finished:
1802                if len(imported):
1803                    transaction.commit()
1804                    datafile = open(imported_path,"a")
1805                    writer = csv.DictWriter(datafile,
1806                                            csv_keys,
1807                                            extrasaction='ignore')
1808                    writer.writerows(imported)
1809                    datafile.close()
1810                    total_added_to_imported += len(imported)
1811                    imported = []
1812                if len(pending) > 0:
1813                    datafile = open(pending_tmp,"a")
1814                    writer = csv.DictWriter(datafile,
1815                                            csv_keys,
1816                                            extrasaction='ignore')
1817                    writer.writerows(pending)
1818                    datafile.close()
1819                    total_pending += len(pending)
1820                    #total_added_to_pending += len(pending)
1821                    pending = []
1822                if not finished:
1823                    msg = '%(commit_after)d records imported and committed of total %(total_added_to_imported)d\n' % vars()
1824                    logger.info(msg)
1825        elapse = time.time() - elapse
1826        if os.path.exists(pending_path):
1827            copy2(pending_path,pending_backup)
1828        copy2(pending_tmp,pending_path)
1829        msg = "finished importing from %(import_source_fn)s in %(elapse).2f seconds, " % vars()
1830        msg += "%(count)d records totally read, %(total_added_to_imported)d added to %(imported_fn)s, " % vars()
1831        if pending_only:
1832            removed_pending = pending_at_start - total_pending
1833            msg += "%(removed_pending)d removed from %(pending_fn)s" % vars()
1834        else:
1835            added_pending = total_pending - pending_at_start
1836            msg += "%(added_pending)d added to %(pending_fn)s, %(already_in)s already in %(pending_fn)s" % vars()
1837        #msg += "%(total_pending)d totally written" % vars()    # this line does not make any sense
1838        logger.info(msg)
1839        if import_source_done:
1840            copy(import_source_path,import_source_done)
1841            os.remove(import_source_path)
1842            upload = getattr(uploads_folder,os.path.split(import_source_path)[1],None)
1843            if upload is not None:
1844                upload_doc = upload.getContent()
1845                mapping = {}
1846                #mapping['import_date'] = DateTime.DateTime()
1847                mapping['import_date'] = import_date
1848                mapping['imported_by'] = importer.imported_by
1849                mapping['import_message'] = msg
1850                upload_doc.edit(mapping = mapping)
1851        os.remove(pending_tmp)
1852        return msg
1853    ###)
1854
1855    security.declareProtected(ModifyPortalContent,"moveImagesToFS")###(
1856    def moveImagesToFS(self,student_id="O738726"):
1857        "move the images to the filesystem"
1858        images_dir = getImagesDir(student_id)
1859        #images_dir = os.path.join("%s" % images_base,student_id)
1860        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1861        stool = getToolByName(self, 'portal_schemas')
1862        schemas = ['student_application',
1863                   'student_clearance',
1864                   ]
1865        created = False
1866        for schema_id in schemas:
1867            schema = stool._getOb(schema_id)
1868            object = getattr(student_folder,schema_id[len('student_'):],None)
1869            if object is None:
1870                continue
1871            doc = object.getContent()
1872            for key in schema.keys():
1873                if schema[key].meta_type != "CPS Image Field":
1874                    continue
1875                #import pdb;pdb.set_trace()
1876                image = getattr(doc,key,None)
1877                if not image or not hasattr(image,"data"):
1878                    continue
1879                if not created:
1880                    if not os.path.exists(images_dir):
1881                        os.mkdir(images_dir)
1882                    created = True
1883                filename = os.path.join(images_dir,"%(key)s_%(student_id)s.jpg" % vars())
1884                open(filename,"wb").write(str(image.data))
1885    ###)
1886
1887    security.declareProtected(ModifyPortalContent,"movePassportToFS")###(
1888    def movePassportToFS(self,student_id="O738726"):
1889        "move the passports to the filesystem"
1890        images_dir = os.path.join("%s" % i_home,'passports')
1891        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1892        stool = getToolByName(self, 'portal_schemas')
1893        schemas = ['student_application',
1894                   #'student_clearance',
1895                   ]
1896        created = False
1897        for schema_id in schemas:
1898            schema = stool._getOb(schema_id)
1899            object = getattr(student_folder,schema_id[len('student_'):],None)
1900            if object is None:
1901                continue
1902            doc = object.getContent()
1903            for key in schema.keys():
1904                if schema[key].meta_type != "CPS Image Field":
1905                    continue
1906                #import pdb;pdb.set_trace()
1907                image = getattr(doc,key)
1908                if not hasattr(image,"data"):
1909                    continue
1910                if not created:
1911                    if not os.path.exists(images_dir):
1912                        os.mkdir(images_dir)
1913                    created = True
1914                filename = os.path.join(images_dir,"%(student_id)s.jpg" % vars())
1915                open(filename,"wb").write(str(image.data))
1916    ###)
1917   
1918   
1919    security.declarePublic('getConfigParams')
1920    def getConfigParams(self,conf_id="configuration"):
1921        conf = getattr(self.portal_url.getPortalObject().campus,conf_id)
1922        conf_obj = conf.getContent()
1923        stool = getToolByName(self, 'portal_schemas')
1924        schema = stool._getOb('configuration')
1925        d = {}
1926        for key in schema.keys():
1927            d[key] = getattr(conf_obj,key,None)
1928        return d
1929
1930
1931InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.