source: WAeUP_SRP/base/WAeUPTool.py @ 2971

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

do not admit students without sex attribute

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