source: WAeUP_SRP/trunk/WAeUPTool.py @ 5614

Last change on this file since 5614 was 5564, checked in by Henrik Bettermann, 14 years ago

Search log files online.

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