source: WAeUP_SRP/base/WAeUPTool.py @ 3205

Last change on this file since 3205 was 3205, checked in by Henrik Bettermann, 17 years ago

add error to logging message

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