source: WAeUP_SRP/base/WAeUPTool.py @ 3203

Last change on this file since 3203 was 3202, checked in by joachim, 17 years ago

remove unnecessary error_counts. The required case is more complicated to do
right.

  • 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 3202 2008-02-23 16:51:51Z joachim $
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        with_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                digest = makeDigest(mapping,data_keys)
1524                if digest not in pending_digests:
1525                    pending_digests += digest,
1526                    pending.append(mapping)
1527                    if not pending_only:
1528                        log_list += "record added to %(pending_fn)s, %(data_string)s" % vars(),
1529                else:
1530                    already_in += 1
1531                    pass
1532            else:
1533                imported_count += 1
1534                imported += mapping,
1535                log_list += "record imported and added to %(imported_fn)s, %(data_string)s" % vars(),
1536            if log_list:
1537                time_till_now = time.time() - elapse
1538                percent_finished = (with_error_count + imported_count)/tti_float*100
1539                log_list.insert(0,("%(percent_finished)6.3f %% done in %(time_till_now)3.2fs," % vars()),)
1540                logger.info(' '.join(log_list))
1541            finished = count > total_to_import - 1
1542            must_commit = False
1543            if len(imported) != old_commit_count:
1544                if not len(imported) % commit_after:
1545                    must_commit = True
1546                    old_commit_count = len(imported)
1547
1548            if must_commit or finished:
1549                if len(imported):
1550                    transaction.commit()
1551                    datafile = open(imported_path,"a")
1552                    writer = csv.DictWriter(datafile,
1553                                            csv_keys,
1554                                            extrasaction='ignore')
1555                    writer.writerows(imported)
1556                    datafile.close()
1557                    total_added_to_imported += len(imported)
1558                    imported = []
1559                if len(pending) > 0:
1560                    datafile = open(pending_tmp,"a")
1561                    writer = csv.DictWriter(datafile,
1562                                            csv_keys,
1563                                            extrasaction='ignore')
1564                    writer.writerows(pending)
1565                    datafile.close()
1566                    total_pending += len(pending)
1567                    #total_added_to_pending += len(pending)
1568                    pending = []
1569                if not finished:
1570                    msg = '%(commit_after)d imports committed of total %(total_added_to_imported)d\n' % vars()
1571                    logger.info(msg)
1572        elapse = time.time() - elapse
1573        copy2(pending_tmp,pending_path)
1574        msg = "finished importing from %(import_source_fn)s in %(elapse).2f seconds, " % vars()
1575        msg += "%(count)d records totally read, %(total_added_to_imported)d added to %(imported_fn)s, " % vars()
1576        if pending_only:
1577            removed_pending = pending_at_start - total_pending
1578            msg += "%(removed_pending)d removed from %(pending_fn)s" % vars()
1579        else:
1580            added_pending = total_pending - pending_at_start
1581            msg += "%(added_pending)d added to %(pending_fn)s, %(already_in)s already in %(pending_fn)s" % vars()
1582        #msg += "%(total_pending)d totally written" % vars()    # this line does not make any sense
1583        logger.info(msg)
1584        os.remove(pending_tmp)
1585        return msg
1586    ###)
1587
1588    def d1402_importData(self,filename,name,edit=False,bypass_queue_catalog=False): ###(
1589        """load data from CSV values"""
1590        import transaction
1591        import random
1592        member = self.portal_membership.getAuthenticatedMember()
1593        logger = logging.getLogger('WAeUPTool.importData')
1594        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1595        import_date = DateTime.DateTime().strftime("%d/%m/%y %H:%M:%S")
1596        students_folder = self.portal_url.getPortalObject().campus.students
1597        start = True
1598        tr_count = 0
1599        total_imported = 0
1600        total_not_imported = 0
1601        total = 0
1602        pending_only = False
1603        pend_str = '_pending'
1604        if name.endswith(pend_str):
1605            pending_only = True
1606            name = name[:-len(pend_str)]
1607        iname = "import_%s" % name
1608        if name in ('application','course_result',):
1609            commit_after = 2000
1610        else:
1611            commit_after = 100
1612        stool = getToolByName(self, 'portal_schemas')
1613        ltool = getToolByName(self, 'portal_layouts')
1614        schema = stool._getOb(iname)
1615        if schema is None:
1616            em = 'No such schema %s' % iname
1617            logger.error('No such schema %s' % iname)
1618            return em
1619        layout = ltool._getOb(iname)
1620        if layout is None:
1621            em = 'No such layout %s' % iname
1622            logger.error(em)
1623            return em
1624        validators = {}
1625        for widget in layout.keys():
1626            validators[widget] = layout[widget].validate
1627        mode = "create"
1628        if edit:
1629            if filename.endswith('_toDelete'):
1630                mode = "delete"
1631            else:
1632                mode = "edit"
1633        importer_name = "mass_%(mode)s_%(name)s" % vars()
1634        importer = getattr(self, '%s' % importer_name,None)
1635        if importer is None:
1636            em = 'No importer function %s' % importer_name
1637            logger.error(em)
1638            return em
1639        pending_fn = "%s/import/%ss_pending.csv" % (i_home,name)
1640        pending_imported_fn = "%s/import/%ss_pending_imported%s.csv" % (i_home,name,current)
1641        if pending_only:
1642            import_source_fn = pending_fn
1643            imported_fn = "%s/import/%ss_pending_imported%s.csv" % (i_home,name,current)
1644            not_imported_fn = "%s/import/%ss_pending_not_imported%s.csv" % (i_home,name,current)
1645            if not os.path.exists(pending_fn):
1646                em = 'No  %s' % os.path.split(pending_fn)
1647                return em
1648        else:
1649            import_source_fn = "%s/import/%s.csv" % (i_home,filename)
1650            imported_fn = "%s/import/%s_imported%s.csv" % (i_home,filename,current)
1651            not_imported_fn = "%s/import/%s_not_imported%s.csv" % (i_home,filename,current)
1652        if not os.path.exists(import_source_fn):
1653            em = 'No  %s' % os.path.split(import_soure_fn)
1654            return em
1655        attrs = csv.reader(open(import_source_fn,"rb")).next()
1656        import_keys = [k.strip() for k in attrs if not (k.strip().startswith('ignore')
1657                                                        or k.strip() == 'Error')]
1658        diff2schema = set(import_keys).difference(set(schema.keys()))
1659        diff2layout = set(import_keys).difference(set(layout.keys()))
1660        if diff2schema and diff2schema != set(['id',]):
1661            msg = 'not ignorable key(s): "%s" found in heading' % ", ".join(diff2schema)
1662            return msg
1663        if mode in ("create","edit"):
1664            required_keys = [layout.getIdUnprefixed(id)
1665                                for id,widget in layout.objectItems()
1666                                if widget.is_required]
1667            if not set(required_keys).issubset(set(import_keys)):
1668                diff2import = set(required_keys).difference(set(import_keys))
1669                msg = 'required key(s): "%s" not found in heading' % ", ".join(diff2import)
1670                return msg
1671        #
1672        # not_imported
1673        #
1674        not_imported_keys = import_keys + ["Error",]
1675        not_imported_file = open(not_imported_fn,"w")
1676        not_imported_csv_writer = csv.DictWriter(not_imported_file,
1677                                                    not_imported_keys,
1678                                                    extrasaction='ignore')
1679        mapping = dict((k,k) for k in not_imported_keys)
1680        not_imported_csv_writer.writerow(mapping)
1681        not_imported = []
1682        #
1683        # imported
1684        #
1685        imported_keys = import_keys[:]
1686        if 'id' not in imported_keys:
1687            imported_keys.insert(0,"id")
1688        imported_file = open(imported_fn,"w")
1689        imported_csv_writer = csv.DictWriter(imported_file,
1690                                             imported_keys,
1691                                             extrasaction='ignore')
1692        mapping = dict((k,k) for k in imported_keys)
1693        imported_csv_writer.writerow(mapping)
1694        imported = []
1695        #
1696        # pending
1697        #
1698        pending_records = {}
1699        imports_pending = 0
1700        total_pending_imported = 0
1701        total_pending = 0
1702        format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
1703        format_error = format + ',"%(Error)s"'
1704        #format = '"%(id)s",'+ format
1705        imported = []
1706        if name in ('verdict','course_result',):
1707            #pending_keys = imported_keys[:]
1708            sname = "%s_pending" % iname
1709            pending_schema = stool._getOb(sname)
1710            if schema is None:
1711                em = 'No such pending_schema %s' % sname
1712                logger.error('No such schema %s' % sname)
1713                return em
1714            pending_keys = pending_schema.keys()
1715            pending_keys += "Error",
1716            if 'id' not in pending_keys:
1717                pending_keys.insert(0,'id')
1718            pending_records = {}
1719            if os.path.exists(pending_fn):
1720                pending_imports_file = open(pending_fn)
1721                pending_imports = csv.DictReader(pending_imports_file,
1722                                                 fieldnames=pending_keys)
1723                if pending_imports:
1724                    pending_records = dict((row['id'],row) for row in pending_imports
1725                                          if row['id'] != 'id')
1726                pending_imports_file.close()
1727            new_imports_pending = 0
1728            pending_imported = []
1729            if pending_only:
1730                pending_imported_ids = []
1731                pending_imported = []
1732                for record in pending_records.values():
1733                    item = {}
1734                    for k,v in record.items():
1735                        if v:
1736                            item[k] = v
1737                    results = importer(item)
1738                    id = results[0]
1739                    error = results[1]
1740                    is_pending = len(results) == 3
1741                    if is_pending:
1742                        continue
1743                    del item['Error']
1744                    msg = ";".join(["%s : %s" % (k,v) for k,v in item.items()])
1745                    logger.info("imported from %(pending_fn)s %(msg)s" % vars())
1746                    pending_imported.append(item)
1747                    pending_imported_ids += id,
1748                    total_pending_imported = len(pending_imported_ids)
1749                    logger.info("imported %d pending imports" % len(pending_imported_ids))
1750                for id in pending_imported_ids:
1751                    if id:
1752                        del pending_records[id]
1753                    else:
1754                        logger.info("tried to delete record with empty id")
1755            pending_imports_file = open(pending_fn,'w')
1756            pending_csv_writer = csv.DictWriter(pending_imports_file,
1757                                                pending_keys,
1758                                                extrasaction='ignore')
1759            mapping = dict((k,k) for k in pending_keys)
1760            pending_csv_writer.writerow(mapping)
1761            if len(pending_imported) > 0:
1762                pending_imported_file = open(pending_imported_fn,'w')
1763                pending_imported_csv_writer = csv.DictWriter(pending_imported_file,
1764                                                             pending_keys,
1765                                                             extrasaction='ignore')
1766                pending_imported_csv_writer.writerow(dict((k,k) for k in imported_keys))
1767                pending_imported_csv_writer.writerows(pending_imported)
1768        #
1769        if pending_only:
1770            items = []
1771        else:
1772            try:
1773                items = csv.DictReader(open(import_source_fn,"rb"))
1774            except:
1775                msg = 'Error reading %s.csv' % filename
1776                logger.error(msg)
1777                return msg
1778            not_imported = []
1779        pending_keys = pending_records.keys()[:]
1780        for item in items:
1781            item = dict((k.strip(),l.strip()) for (k,l) in item.items())
1782            if start:
1783                start = False
1784                adapters = [MappingStorageAdapter(schema, item)]
1785                logger.info('%s starts import from %s.csv in %s mode with schema and layout %s' % (member,filename,mode,iname))
1786            dm = DataModel(item, adapters,context=self)
1787            ds = DataStructure(data=item,datamodel=dm)
1788            error_string = ""
1789            total += 1
1790            error_count = 0
1791            for k in import_keys:
1792                if not validators[k](ds,mode=mode):
1793                    if error_count:
1794                        error_string += ' ++ '
1795                    error_string += "%s: %s" % (k,self.translation_service(ds.getError(k),
1796                                                                           ds.getErrorMapping(k)))
1797                    error_count += 1
1798            if error_string:
1799                item['Error'] = error_string
1800                not_imported.append(item)
1801                total_not_imported += 1
1802                continue
1803            temp_item = item.copy()
1804            temp_item.update(dm)
1805            #id,error = importer(temp_item)
1806            results = importer(temp_item)
1807            id = results[0]
1808            error = results[1]
1809            is_pending = len(results) == 3
1810            if is_pending:
1811                temp_item = results[2]
1812                temp_item['Error'] = error
1813                msg = format_error % temp_item
1814                #if id not in pending_records.keys():
1815                if id not in pending_keys:
1816                    temp_item['id'] = id
1817                    pending_records[id] = temp_item
1818                    logger.info("%(id)s added to pending %(msg)s" % vars())
1819                    pending_keys += id,
1820                    new_imports_pending += 1
1821                else:
1822                    logger.info("%(id)s already in pending %(msg)s" % vars())
1823                continue
1824            elif error:
1825                item['Error'] = error
1826                not_imported.append(item)
1827                total_not_imported += 1
1828                continue
1829            item = temp_item
1830            item['id'] = id
1831            imported.append(item)
1832            tr_count += 1
1833            total_imported += 1
1834            msg = format % item
1835            logger.info("%(total_imported)d of %(total)d imported in %(mode)s mode, %(msg)s" % vars())
1836            if total and not total % commit_after:
1837                transaction.commit()
1838                if len(imported) > 0:
1839                    imported_csv_writer.writerows(imported)
1840                    imported = []
1841                if len(not_imported) > 0:
1842                    not_imported_csv_writer.writerows(not_imported)
1843                    not_imported = []
1844                if len(pending_records) > 0:
1845                    pending_csv_writer.writerows(pending_records.values())
1846                    total_pending += len(pending_records)
1847                    pending_records = {}
1848                msg = '%d transactions committed\n' % (tr_count)
1849                regs = []
1850                logger.info(msg)
1851                tr_count = 0
1852        if len(imported) > 0:
1853            imported_csv_writer.writerows(imported)
1854        if len(not_imported) > 0:
1855            not_imported_csv_writer.writerows(not_imported)
1856        if len(pending_records) > 0:
1857            pending_csv_writer.writerows(pending_records.values())
1858            total_pending += len(pending_records)
1859        import_source_fn = os.path.split(import_source_fn)[1]
1860        pending_fn = os.path.split(pending_fn)[1]
1861        msg = "Finished importing in %(mode)s mode from %(import_source_fn)s: " % vars()
1862        msg += "%(total_imported)d imported, %(total_not_imported)d not imported, " % vars()
1863        if total_pending:
1864            if pending_only:
1865                msg += "%(new_imports_pending)d pending added, %(total_pending_imported)d pending imported " % vars()
1866            else:
1867                msg += "%(new_imports_pending)d pending added " % vars()
1868            msg += "(of total %(total)d), " % vars()
1869            msg += "%(total_pending)d total pending in %(pending_fn)s " % vars()
1870        logger.info(msg)
1871        return msg
1872    ###)
1873
1874    security.declareProtected(ModifyPortalContent,"moveImagesToFS")###(
1875    def moveImagesToFS(self,student_id="O738726"):
1876        "move the images to the filesystem"
1877        images_dir = getImagesDir(student_id)
1878        #images_dir = os.path.join("%s" % images_base,student_id)
1879        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1880        stool = getToolByName(self, 'portal_schemas')
1881        schemas = ['student_application',
1882                   'student_clearance',
1883                   ]
1884        created = False
1885        for schema_id in schemas:
1886            schema = stool._getOb(schema_id)
1887            object = getattr(student_folder,schema_id[len('student_'):],None)
1888            if object is None:
1889                continue
1890            doc = object.getContent()
1891            for key in schema.keys():
1892                if schema[key].meta_type != "CPS Image Field":
1893                    continue
1894                #import pdb;pdb.set_trace()
1895                image = getattr(doc,key,None)
1896                if not image or not hasattr(image,"data"):
1897                    continue
1898                if not created:
1899                    if not os.path.exists(images_dir):
1900                        os.mkdir(images_dir)
1901                    created = True
1902                filename = os.path.join(images_dir,"%(key)s_%(student_id)s.jpg" % vars())
1903                open(filename,"wb").write(str(image.data))
1904    ###)
1905
1906    security.declareProtected(ModifyPortalContent,"movePassportToFS")###(
1907    def movePassportToFS(self,student_id="O738726"):
1908        "move the passports to the filesystem"
1909        images_dir = os.path.join("%s" % i_home,'passports')
1910        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1911        stool = getToolByName(self, 'portal_schemas')
1912        schemas = ['student_application',
1913                   #'student_clearance',
1914                   ]
1915        created = False
1916        for schema_id in schemas:
1917            schema = stool._getOb(schema_id)
1918            object = getattr(student_folder,schema_id[len('student_'):],None)
1919            if object is None:
1920                continue
1921            doc = object.getContent()
1922            for key in schema.keys():
1923                if schema[key].meta_type != "CPS Image Field":
1924                    continue
1925                #import pdb;pdb.set_trace()
1926                image = getattr(doc,key)
1927                if not hasattr(image,"data"):
1928                    continue
1929                if not created:
1930                    if not os.path.exists(images_dir):
1931                        os.mkdir(images_dir)
1932                    created = True
1933                filename = os.path.join(images_dir,"%(student_id)s.jpg" % vars())
1934                open(filename,"wb").write(str(image.data))
1935    ###)
1936
1937InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.