source: WAeUP_SRP/trunk/WAeUPTool.py @ 12610

Last change on this file since 12610 was 8298, checked in by Henrik Bettermann, 13 years ago

Add public getSchoolFess method.

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