source: WAeUP_SRP/base/WAeUPTool.py @ 3173

Last change on this file since 3173 was 3172, checked in by joachim, 17 years ago

import completely reworked.

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