source: WAeUP_SRP/trunk/WAeUPTool.py @ 5321

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

resolve #690

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