source: WAeUP_SRP/base/WAeUPTool.py @ 3226

Last change on this file since 3226 was 3219, checked in by joachim, 17 years ago

check if required fields are present in data-record

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