source: WAeUP_SRP/base/WAeUPTool.py @ 2357

Last change on this file since 2357 was 2354, checked in by joachim, 17 years ago

make File Image Widget work with all filetypes

  • Property svn:keywords set to Id
File size: 62.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 2354 2007-10-12 11:21:52Z joachim $
20"""The WAeUP Tool Box.
21"""
22
23from AccessControl import ClassSecurityInfo
24from Acquisition import aq_inner
25from Acquisition import aq_parent
26from Globals import DTMLFile
27from Globals import InitializeClass
28from OFS.SimpleItem import SimpleItem
29from zExceptions import BadRequest
30
31from Products.CMFCore.utils import getToolByName
32from Products.CPSSchemas.DataStructure import DataStructure
33from Products.CPSSchemas.DataModel import DataModel
34from Products.CPSSchemas.StorageAdapter import MappingStorageAdapter
35from Products.CMFCore.ActionProviderBase import ActionProviderBase
36from Products.CMFCore.permissions import View
37from Products.ZCatalog.ZCatalog import ZCatalog
38from Products.CMFCore.permissions import ModifyPortalContent
39from Products.CMFCore.permissions import ManagePortal
40from Products.CMFCore.utils import UniqueObject
41from Products.CMFCore.URLTool import URLTool
42from Products.CMFCore.utils import getToolByName
43from Students import makeCertificateCode
44from Globals import package_home,INSTANCE_HOME
45p_home = package_home(globals())
46i_home = INSTANCE_HOME
47import DateTime,time
48import logging
49import transaction
50import csv,re,os,sys
51from Products.AdvancedQuery import Eq, Between, Le,In
52
53def getObject(object,name):
54    if object.hasObject(name):
55        return getattr(object,name)
56    return None
57
58class WAeUPTool(UniqueObject, SimpleItem, ActionProviderBase):
59    """WAeUP tool"""
60
61    id = 'waeup_tool'
62    meta_type = 'WAeUP Tool'
63    _actions = ()
64    security = ClassSecurityInfo()
65    security.declareObjectProtected(View)
66    manage_options = ( ActionProviderBase.manage_options
67                     + SimpleItem.manage_options
68                     )
69
70    def rwrite(self,s): ###(
71        response = self.REQUEST.RESPONSE
72        response.setHeader('Content-type','text/html; charset=ISO-8859-15')
73        response.write("%s<br />\r\n" % s)
74    ###)
75
76    def sleep(self,secs): ###(
77        "sleep"
78        import time
79        time.sleep(secs)
80        return
81
82###)
83
84    security.declareProtected(ModifyPortalContent,'openLog') ###(
85    def openLog(self,name):
86        """open a log file"""
87        version = 1
88        path = "%s/log/%s_%d.log" % (i_home,name,version)
89        while os.path.exists(path):
90            version += 1
91            path = "%s/log/%s_%d.log" % (i_home,name,version)
92        log = open(path,"w")
93        return log
94    ###)
95
96    security.declareProtected(ModifyPortalContent,'bypassQueueCatalog') ###(
97    def bypassQueueCatalog(self,enable=True):
98        """bypass the QueueCatalog by setting all indexes to process imediate,
99        if enable is True (default) the old settings are restored
100        """
101
102    ###)
103
104    security.declareProtected(ModifyPortalContent,'measureOaT') ###(
105    def measureOaT(self,method="a",probe="1000",nr_pts="1"):
106        """measure Object access Time"""
107        import random
108        if hasattr(self,'portal_catalog_real'):
109            aq_portal = self.portal_catalog_real.evalAdvancedQuery
110        else:
111            aq_portal = self.portal_catalog.evalAdvancedQuery
112        nr_pts = int(nr_pts)
113        probe = int(probe)
114        intervall = probe/10
115        objects = ("application","clearance","personal")
116        portal_types = ("StudentApplication","StudentClearance","StudentPersonal")
117        #i = random.randrange(num_objects)
118        count = 0
119        found = 0
120        not_found = 0
121        t_found = 0
122        t_not_found = 0
123        time_found = time_not_found = 0.0
124        t_time_found = t_time_not_found = 0.0
125        accessed = []
126        t_min = 1000
127        t_max = 0
128        #import pdb;pdb.set_trace()
129        students = self.portal_catalog(portal_type="Student")
130        num_students = len(students)
131        if method == "d":
132            query = Eq('path','/uniben/campus/students') & In('portal_type',portal_types[:nr_pts])
133            res = aq_portal(query)
134            brains = {}
135            for r in res:
136                sid = r.relative_path.split('/')[-2]
137                if brains.has_key(sid):
138                    brains[sid][r.portal_type] = r
139                else:
140                    brains[sid] = {r.portal_type : r}
141            brains_list = brains.keys()
142            num_objects = len(brains_list)
143        else:
144            num_objects = num_students
145        print "="*40
146        print "method: %s probes: %d nr_pts: %d num_objects: %d" % (method,
147                                                                        probe,
148                                                                        nr_pts,
149                                                                        num_objects)
150        print "nr found/not time found/not min/max"
151        elapse = time.time()
152        i_elapse = time.time()
153        c_elapse = time.clock()
154        for c in range(1,probe + 1):
155            i = random.randrange(num_objects)
156            if method in ('a','b','c'):
157                student_brain = students[i]
158            elif method == "d":
159                #import pdb;pdb.set_trace()
160                student_brain = brains[brains_list[i]]
161            if method == "c":
162                query = Eq('path',student_brain.getPath()) & In('portal_type',portal_types[:nr_pts])
163                res = aq_portal(query)
164                this_portal_types = [r.portal_type for r in res]
165            for i in range(nr_pts):
166                oid = objects[i]
167                if method == "a":
168                    try:
169                        student_path = student_brain.getPath()
170                        path = "%s/%s" % (student_path,oid)
171                        doc = self.unrestrictedTraverse(path).getContent()
172                        found += 1
173                        i_time = time.time() - i_elapse
174                        time_found += i_time
175                    except:
176                        not_found += 1
177                        i_time = time.time() - i_elapse
178                        time_not_found += i_time
179                        pass
180                elif method == "b":
181                    try:
182                        student_object = student_brain.getObject()
183                        doc = getattr(student_object,oid).getContent()
184                        found += 1
185                        i_time = time.time() - i_elapse
186                        time_found += i_time
187                    except:
188                        i_time = time.time() - i_elapse
189                        time_not_found += i_time
190                        not_found += 1
191                        pass
192                elif method == "c":
193                    if portal_types[i] in this_portal_types:
194                        found += 1
195                        doc = res[this_portal_types.index(portal_types[i])].getObject().getContent()
196                        i_time = time.time() - i_elapse
197                        time_found += i_time
198                    else:
199                        not_found += 1
200                        i_time = time.time() - i_elapse
201                        time_not_found += i_time
202                elif method == "d":
203                    if student_brain.has_key(portal_types[i]):
204                        found += 1
205                        doc = student_brain[portal_types[i]].getObject().getContent()
206                        i_time = time.time() - i_elapse
207                        time_found += i_time
208                    else:
209                        not_found += 1
210                        i_time = time.time() - i_elapse
211                        time_not_found += i_time
212                i_elapse = time.time()
213            if c and (c % intervall == 0):
214                #i_time = time.time() - i_elapse
215                t_per = 0.0
216                if found:
217                    t_per = time_found/found
218                if t_per > t_max:
219                    t_max = t_per
220                if t_per > 0.0 and t_per < t_min:
221                    t_min = t_per
222                itf = 0.0
223                if found:
224                    itf = time_found/found
225                itnf = 0.0
226                if not_found :
227                    itnf = time_not_found / not_found
228                interval_time = time_found + time_not_found
229                s = "%(c)d: %(found)d/%(not_found)d " % vars()
230                s += "%(interval_time)6.2f %(itf)6.4f/%(itnf)6.4f " % vars()
231                s += "%(t_min)6.4f/%(t_max)6.4f" %  vars()
232                print s
233                t_found += found
234                t_not_found += not_found
235                t_time_found += time_found
236                t_time_not_found += time_not_found
237                time_found = time_not_found = 0.0
238                found = not_found = 0
239        # t_found += found
240        # t_not_found += not_found
241        elapse = time.time() - elapse
242        itf = 0.0
243        if t_found:
244            itf = t_time_found/t_found
245        itnf = 0.0
246        if t_not_found:
247            itnf = t_time_not_found / t_not_found
248        #c_elapse = time.clock() - c_elapse
249        s = "%(probe)d: %(t_found)d/%(t_not_found)d " % vars()
250        s += "%(elapse)6.2f %(itf)6.4f/%(itnf)6.4f " % vars()
251        s += "%(t_min)6.4f/%(t_max)6.4f" %  vars()
252        print "-"*40
253        print s
254        rel_found = float(t_found)/probe
255        rel_not_found = float(t_not_found)/probe
256        estimated_total_time = num_objects*(rel_found*itf + rel_not_found*itnf)
257        print estimated_total_time
258    ###)
259
260    security.declareProtected(ModifyPortalContent,'writeLog') ###(
261    def writeLog(self,logfile,s):
262        """write to the log file"""
263        logfile.write(s)
264
265###)
266
267    def generateStudentId(self,letter): ###(
268        import random
269        r = random
270        ##if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
271        if letter == '?':
272            letter= r.choice('ABCDEFGHKLMNPQRSTUVWXY')
273        sid = "%c%d" % (letter,r.randint(99999,1000000))
274        students = self.portal_url.getPortalObject().campus.students
275##        while hasattr(students, sid):
276##            sid = "%c%d" % (letter,r.randint(99999,1000000))
277        while self.students_catalog(id = sid):
278            sid = "%c%d" % (letter,r.randint(99999,1000000))
279        return sid
280    ###)
281
282    def generatePassword(self,s=None): ###(
283        import random
284        r = random
285        ##if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
286        if s is None:
287            s = 'abcdefghklmnpqrstuvwxy23456789'
288        pw = ''
289        while len(pw) < 6:
290            pw += r.choice(s)
291        return pw
292    ###)
293
294    security.declareProtected(ManagePortal, 'removeDeletedDocIds') ###(
295    def removeDeletedDocIds(self, max=1000):
296        """
297        remove deleted docids from repository commit after max
298        """
299        logger = logging.getLogger('WAeUPTool.removeDeletedDocIds')
300        repository = getToolByName(self, 'portal_repository')
301        pxtool = getToolByName(self, 'portal_proxies')
302        pxtool_infos = pxtool.getRevisionsUsed()
303
304        nb_revs = 0
305        docids_d = {} # all docids
306        unused_docids_d = {} # all docids that are unused
307        ids_unused_revs_docids = [] # ids for revs of unused docids
308        ids_unused_revs = [] # ids for unused revs
309        total = 0
310        idlist = repository.objectIds()
311        for id in idlist:
312            docid, rev = repository._splitId(id)
313            if docid is None:
314                logger.info("invalid doc_id %s" % docid)
315                continue
316            nb_revs += 1
317            docids_d[docid] = None
318            if not pxtool_infos.has_key(docid):
319                unused_docids_d[docid] = None
320                ids_unused_revs_docids.append(id)
321                ids_unused_revs.append(id)
322            elif not pxtool_infos[docid].has_key(rev):
323                ids_unused_revs.append(id)
324            if len(ids_unused_revs) >= max:
325                repository.manage_delObjects(ids_unused_revs)
326                #import pdb;pdb.set_trace()
327                transaction.commit()
328                total += max
329                logger.info('removed %d total %d unused docids ' % (max,total))
330        anz = len(ids_unused_revs)
331        if anz > 0:
332            repository.manage_delObjects(ids_unused_revs)
333            transaction.commit()
334            total += anz
335            logger.info('finished removing %d unused docids ' % (total))
336
337
338###)
339
340    security.declareProtected(View,'getCredential') ###(
341    def getCredential(self,student_id):
342        "return a student password"
343        student_entry = getattr(self.portal_directories.students,student_id,None)
344        if student_entry is None:
345            return None
346        return getattr(student_entry,"password","not set")
347    ###)
348
349    security.declarePublic('checkPassword') ###(
350    def checkPassword(self,student_id,password):
351        "return a student password"
352        student_entry = getattr(self.portal_directories.students,student_id,None)
353        if student_entry is None:
354            return False
355        return getattr(student_entry,"password","not set") == password
356    ###)
357
358    security.declarePublic('editPassword') ###(
359    def editPassword(self,student_id,password):
360        "edit a student password"
361        student_entry = getattr(self.portal_directories.students,student_id,None)
362        if student_entry is None:
363            return
364        setattr(student_entry,'password',password)
365    ###)
366
367    security.declareProtected(View,'doCommit') ###(
368    def doCommit(self,logger=None):
369        "commit some transactions"
370        transaction.commit()
371    ###)
372
373    security.declarePublic('loadStudentFoto') ###(
374    def loadStudentFoto(self,student,filename,folder):
375        "return a student passport picture"
376        app = student.application
377        app_doc = app.getContent()
378        #clear = student.clearance
379        #clear_doc = clear.getContent()
380        #matric_no = clear_doc.matric_no.upper()
381        picture1 ="%s/import/%s/%s.jpg" % (i_home,folder,filename)
382        picture2 ="%s/import/%s/%s.JPG" % (i_home,folder,filename)
383        #import pdb;pdb.set_trace()
384        if os.path.exists(picture1):
385            file = open(picture1)
386        elif os.path.exists(picture2):
387            file = open(picture2)
388        else:
389            return "passport picture not found %s" % picture1
390        reopened = False
391        if self.portal_workflow.getInfoFor(app,'review_state',None) !='opened':
392            self.portal_workflow.doActionFor(app,'open')
393            reopened = True
394        outfile = file.read()
395        app_doc.manage_addFile('passport',
396                               file=outfile,
397                               title="%s.jpg" % filename)
398        if reopened:
399            self.portal_workflow.doActionFor(app,'close')
400        return "successfully loaded passport picture"
401    ###)
402
403    security.declareProtected(ModifyPortalContent,'createOne') ###(
404    def createOne(self,students_folder,student_brain,letter,commit=False):
405        sid = self.waeup_tool.generateStudentId(letter)
406        students_folder.invokeFactory('Student', sid)
407        student = getattr(students_folder,sid)
408        self.portal_workflow.doActionFor(student,'return')
409        student.manage_setLocalRoles(sid, ['Owner',])
410        matric_no = student_brain.matric_no
411        jamb_reg_no = student_brain.Entryregno
412        self.students_catalog.addRecord(id = sid,
413                                           matric_no = matric_no,
414                                           jamb_reg_no = jamb_reg_no,
415                                           sex = student_brain.Sex == "F",
416                                           name = "%s %s %s" % (student_brain.Firstname,
417                                                                student_brain.Middlename,
418                                                                student_brain.Lastname)
419                                        )
420        if commit:
421            transaction.commit()
422        return sid,jamb_reg_no
423    ###)
424
425    security.declareProtected(ModifyPortalContent,'addStudent') ###(
426    def addStudent(self,dict):
427        students_folder = self.portal_url.getPortalObject().campus.students
428        sid = self.waeup_tool.generateStudentId('?')
429        students_folder.invokeFactory('Student', sid)
430        student_obj = getattr(students_folder,sid)
431        f2t = self.student_field2types
432        #from pdb import set_trace; set_trace()
433        d = {}
434        #d['jamb_sex']  = 'M'
435        #if dict.get('sex'):
436        #    d['jamb_sex']  = 'F'
437
438        entry_session = dict.get('entry_session')
439        if entry_session == self.getSessionId()[-2:]:
440            wfaction = 'admit'
441            wft = 'wf_transition_admit'
442            password = None
443        else:
444            wfaction = 'return'
445            wft = 'wf_transition_return'
446            password = self.generatePassword()
447            self.makeStudentMember(sid,password)
448
449        for pt in f2t.keys():
450            student_obj.invokeFactory(pt,f2t[pt]['id'])
451            sub_obj = getattr(student_obj,f2t[pt]['id'])
452            sub_doc = sub_obj.getContent()
453            #self.portal_workflow.doActionFor(sub_obj,'open',dest_container=sub_obj)
454            d['Title'] = f2t[pt]['title']
455            for field in f2t[pt]['fields']:
456                d[field] = dict.get(field,'')
457            sub_doc.edit(mapping = d)
458            new_state = f2t[pt][wft]
459            if new_state != "remain":
460                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
461        self.portal_workflow.doActionFor(student_obj,wfaction)
462        student_obj.manage_setLocalRoles(sid, ['Owner',])
463        return sid,password
464    ###)
465
466    security.declarePublic('getCertificateBrain') ###(
467    def getCertificateBrain(self,cert_id):
468        "do it"
469        res = ZCatalog.searchResults(self.portal_catalog_real,
470                                {'portal_type':"Certificate",
471                                      'id': cert_id})
472        if res:
473            return res[0]
474        return None
475    ###)
476
477    security.declareProtected(ModifyPortalContent,'get_csv_filenames') ###(
478    def get_csv_filenames(self):
479        "do it"
480        files = [file for file in os.listdir("%s/import/" % (i_home))
481                 if file.endswith('.csv') and file.find('imported') == -1]
482        return files
483    ###)
484
485    security.declarePublic('findStudentByMatricelNo') ###(
486    def findStudentByMatricelNo(self,matric_no):
487        "do it"
488        res = ZCatalog.searchResults(self.portal_catalog_real,
489                                {'portal_type':"StudentClearance",
490                                 'SearchableText': matric_no})
491        if res:
492            return res[0]
493        return None
494    ###)
495
496    security.declarePublic('makeStudentMember') ###(
497    def makeStudentMember(self,sid,password='uNsEt'):
498        """make the student a member"""
499        membership = self.portal_membership
500        membership.addMember(sid,
501                             password ,
502                             roles=('Member',
503                                     'Student',
504                                     ),
505                             domains='',
506                             properties = {'memberareaCreationFlag': False,
507                                           'homeless': True},)
508        member = membership.getMemberById(sid)
509        self.portal_registration.afterAdd(member, sid, password, None)
510        #self.manage_setLocalRoles(sid, ['Owner',])
511    ###)
512
513    security.declarePublic('makeStudentData') ###(
514    def makeStudentData(self,student_id,email=None,phone_nr=None):
515        "create Datastructure for a returning Student"
516        #import pdb;pdb.set_trace()
517        logger = logging.getLogger('WAeUPTool.makeStudentData')
518        students_folder = self.portal_url.getPortalObject().campus.students
519        #res = self.students_catalog(id=student_id)
520        #if res:
521        #    st = res[0]
522        #res = self.returning_import(matric_no = st.matric_no)
523        res = self.returning_import(id = student_id)
524        if res:
525            student = res[0]
526        else:
527            logger.info('Id %s not found in returning_import' % student_id)
528            return
529        logger.info('%s creates data structure' % student_id)
530        s_results = self.results_import(matric_no = student.matric_no)
531        if s_results:
532            lnr = self.getLevelFromResultsCosCode(s_results)
533            level = "%d00" % lnr
534            verdict,eligible = self.getVerdict(s_results[0].Verdict)
535            if eligible:
536                level = "%d00" % (lnr + 1)
537        else:
538            logger.info('matric_no %s not found in results_import' % student.matric_no)
539            level = 0
540            verdict = 'N/A'
541        #student should not be allowed to perform this transition
542        #wftool = self.portal_workflow
543        #wftool.doActionFor(student,'return')
544        certcode_org = student.Coursemajorcode
545        certcode = makeCertificateCode(certcode_org)
546        certificate_brain = self.getCertificateBrain(certcode)
547        if not certificate_brain:
548            em = 'Certificate %s org-code %s not found\n' % (certcode, certcode_org)
549            logger.info(em)
550        matric_no = student.matric_no
551        sid = student_id
552        student_obj = getattr(students_folder,sid)
553        student_obj.invokeFactory('StudentApplication','application')
554        application = student_obj.application
555        self.portal_workflow.doActionFor(application,'open',dest_container=application)
556        da = {'Title': 'Application Data'}
557        student_obj.invokeFactory('StudentPersonal','personal')
558        da['jamb_reg_no'] = student.Entryregno
559        em = self.getEntryMode(student.Entryregno)
560##        em = student.Mode_of_Entry
561##        if em in ('DIRECT', 'DIRECT ENTRY',):
562##            em = 'DE'
563##        elif em in ('U.M.E', 'UNE',):
564##            em = 'UME'
565##        elif not em:
566##            em = "unknown"
567        da['entry_mode'] = em
568        personal = student_obj.personal
569        self.portal_workflow.doActionFor(personal,'open',dest_container=personal)
570        dp = {'Title': 'Personal Data'}
571        student_obj.invokeFactory('StudentClearance','clearance')
572        clearance = student_obj.clearance
573        self.portal_workflow.doActionFor(clearance,'open',dest_container=clearance)
574        dc = {'Title': 'Clearance/Eligibility Record'}
575        dc['matric_no'] = matric_no
576        state = student.State
577        lga = student.LGA
578        if state and lga:
579            lga =  state + ' / ' + lga
580        else:
581            lga = "None"
582        da['jamb_lga'] = dc['lga'] = lga
583        da['app_email'] = dp['email'] = email
584        da['app_mobile'] = dp['phone'] = phone_nr
585        dp['firstname'] = student.Firstname
586        dp['middlename'] = student.Middlename
587        dp['lastname'] = student.Lastname
588        da['jamb_lastname'] = "%s %s %s" % (student.Firstname,student.Middlename,student.Lastname)
589        da['jamb_sex'] = student.Sex
590        dp['sex'] = student.Sex == 'F'
591        dp['perm_address'] = student.Permanent_Address
592        application.getContent().edit(mapping=da)
593        self.portal_workflow.doActionFor(application,'close',dest_container=application)
594        personal.getContent().edit(mapping=dp)
595        clearance.getContent().edit(mapping=dc)
596        self.portal_workflow.doActionFor(clearance,'close',dest_container=clearance)
597##        catd = {}
598##        catd['id'] = sid
599##        catd['entry_mode']= da['entry_mode']
600##        catd['matric_no'] = matric_no
601##        catd['jamb_reg_no'] = da['jamb_reg_no']
602##        catd['name'] = "%(firstname)s %(middlename)s %(lastname)s" % dp
603##        catd['sex'] = dp['sex']
604##        catd['level'] = level
605##        catd['verdict'] = verdict
606##        if certificate_brain:
607##            cpath = certificate_brain.getPath().split('/')
608##            catd['faculty'] = cpath[-4]
609##            catd['department'] = cpath[-3]
610##            catd['course'] = certcode
611##        self.students_catalog.modifyRecord(**catd)
612        #
613        # Study Course
614        #
615        student_obj.invokeFactory('StudentStudyCourse','study_course')
616        studycourse = student_obj.study_course
617        self.portal_workflow.doActionFor(studycourse,'open',dest_container=studycourse)
618        dsc = {}
619        dsc['study_course'] = certcode
620        dsc['current_level'] = level
621        dsc['current_verdict'] = verdict
622        dsc['current_mode'] = em
623        dsc['current_session'] = '06'
624        studycourse.getContent().edit(mapping=dsc)
625        #
626        # Level
627        #
628##        l = getattr(studycourse,level,None)
629##        if l is None:
630##            studycourse.invokeFactory('StudentStudyLevel', level)
631##            l = getattr(studycourse, level)
632##            self.portal_workflow.doActionFor(l,'open',dest_container=l)
633##            l.getContent().edit(mapping={'Title': "Level %s" % level})
634###)
635
636    security.declarePublic('makeStudentLevel') ###(
637    def makeStudentLevel(self,student_id):
638        "create the StudyLevel for a returning Student"
639        #import pdb;pdb.set_trace()
640        logger = logging.getLogger('WAeUPTool.makeStudentLevel')
641        students_folder = self.portal_url.getPortalObject().campus.students
642        res = self.students_catalog(id=student_id)
643        if res:
644            st = res[0]
645        course = st.course
646        matric_no = st.matric_no
647        level = st.level
648        res = self.results_import(matric_no = matric_no)
649        if res:
650            results = res
651        logger.info('%s creating Level %s' % (student_id,level))
652        #
653        # Level
654        #
655        student_obj = getattr(self.portal_url.getPortalObject().campus.students,student_id)
656        studycourse = getattr(student_obj,"study_course",None)
657        self.portal_workflow.doActionFor(studycourse,'close_for_edit',dest_container=studycourse)
658        l = getattr(studycourse,level,None)
659        if l is None:
660            studycourse.invokeFactory('StudentStudyLevel', level)
661            l = getattr(studycourse, level)
662            self.portal_workflow.doActionFor(l,'open',dest_container=l)
663            l.getContent().edit(mapping={'Title': "Level %s" % level})
664        ###)
665
666    security.declarePublic('getHallInfo') ###(
667    def getHallInfo(self,bed):
668        """return Hall Info"""
669        info = {}
670        hall,block,room,letter = bed.split('_')
671        res = ZCatalog.searchResults(self.portal_catalog_real,portal_type="AccoHall",id=hall)
672        if res and len(res) == 1:
673            hall_brain = res[0]
674            hall_doc = hall_brain.getObject().getContent()
675        else:
676            return info
677        info['hall_title'] = hall_brain.Title
678        info['maintenance_code'] = hall_doc.maintenance_code
679        res = ZCatalog.searchResults(self.portal_catalog_real,portal_type="ScratchCardBatch")
680        batch_doc = None
681        for brain in res:
682            if brain.id.startswith(info['maintenance_code']):
683                batch_doc = brain.getObject().getContent()
684                break
685        if batch_doc is None:
686            info['maintenance_fee'] = None
687        else:
688            info['maintenance_fee'] = batch_doc.cost
689        return info
690    ###)
691
692    security.declarePublic('showFsPicture') ###(
693    def showFsPicture(self,path):
694        """return a picture from the filesystem"""
695        picture_path = os.path.join(i_home,path)
696        response = self.REQUEST.RESPONSE
697        #import pdb;pdb.set_trace()
698        registry = getToolByName(self, 'mimetypes_registry')
699        mimetype = str(registry.lookupExtension(path.lower()) or
700                    registry.lookupExtension('file.bin'))
701        if os.path.exists(picture_path):
702            response.setHeader('Content-type',mimetype)
703            return open(picture_path).read()
704        picture_path = os.path.join(i_home,'import',path)
705        if os.path.exists(picture_path):
706            return open(picture_path).read()
707
708
709    ###)
710
711    security.declareProtected(ModifyPortalContent,'deleteAllCourses') ###(
712    def deleteAllCourses(self,department="All"):
713        ''' delete the courses'''
714        pm = self.portal_membership
715        member = pm.getAuthenticatedMember()
716
717        if str(member) not in ("henrik","joachim"):
718            return "not possible"
719        if department == "All":
720            res = self.portal_catalog({'meta_type': 'Department'})
721        if len(res) < 1:
722            return "No Departments found"
723
724        deleted = []
725        for dep in res:
726            cf = dep.getObject().courses
727            if cf:
728                cf.manage_delObjects(ids=cf.objectIds())
729                deleted.append("deleted Courses in %s" % dep.getId)
730        return "\r".join(deleted)
731    ###)
732
733    security.declareProtected(ModifyPortalContent,'getLogfileLines') ###(
734    def getLogfileLines(self,filename="event.log",numlines=20):
735        """Get last NUMLINES lines of logfile FILENAME.
736
737        Return last lines' of a file in the instances logfile directory as
738        a list. The number of returned lines equals `numlines' or less. If
739        less than `numlines' lines are available, the whole file ist
740        returned. If the file can not be opened or some other error
741        occurs, empty list is returend.
742        """
743        result = []
744        lines_hit = 0
745
746        # We only handle files in instances' log directory...
747        logpath = os.path.join(i_home, "log")
748        filename = str(os.path.abspath( os.path.join( logpath, filename )))
749        if not filename.startswith( logpath ):
750            # Attempt to access file outside log-dir...
751            return []
752
753        try:
754            fd = file( filename, "rb" )
755        except IOError:
756            return []
757        if not fd:
758            return []
759
760        if os.linesep == None:
761            linesep = '\n'
762        else:
763            linesep = os.linesep
764
765        # Try to find 'numlines' times a lineseparator, searching from end
766        # and moving to the beginning of file...
767        fd.seek( 0, 2) # Move to end of file...
768        while lines_hit < numlines:
769            if fd.read(1) == linesep[-1]: # This moves filedescriptor
770                                          # one step forward...
771                lines_hit += 1
772            try:
773                fd.seek( -2, 1) # Go two bytes back from current pos...
774            except IOError:
775                # We cannot go back two bytes. Maybe the file is too small...
776                break
777        fd.seek(2,1)
778
779        # Read all lines from current position...
780        result = fd.readlines()
781        # Remove line endings...
782        result = [x.strip() for x in result]
783        fd.close()
784        return result
785    ###)
786
787    security.declareProtected(ModifyPortalContent,"getCallbacksFromLog")###(
788    def getCallbacksFromLog(self,filename):
789        """fix Online Payment Transactions from Z2.log entries"""
790        import transaction
791        import random
792        from cgi import parse_qs
793        from urlparse import urlparse
794        #from pdb import set_trace
795        wftool = self.portal_workflow
796        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
797        students_folder = self.portal_url.getPortalObject().campus.students
798        s = r'(?P<client_ip>\S+) - (?P<member_id>\S+) \['
799        s += r'(?P<date>.*)\] "(?P<get>.*)" (?P<codes>\d+ \d+) "'
800        s += r'(?P<intersw>.*)" "(?P<agent>.*)"'
801        data = re.compile(s)
802        start = True
803        tr_count = 1
804        total = 0
805        #name = 'pume_results'
806        #name = 'epaymentsuccessful_z2log2'
807        name = filename
808        no_import = []
809        imported = []
810        logger = logging.getLogger('WAeUPTool.getFailedTransactions')
811        try:
812            transactions = open("%s/import/%s" % (i_home,name),"rb").readlines()
813        except:
814            logger.error('Error reading %s' % name)
815            return
816        tas = []
817        for line in transactions:
818            dict = {}
819            items = data.search(line)
820            dict['idict'] = idict = items.groupdict()
821            #print idict
822            #from pdb import set_trace;set_trace()
823            urlparsed = urlparse(idict['get'][4:])
824            #print urlparsed
825            path = urlparsed[2].split('/')
826            dict['student_id'] = student_id = path[8]
827            dict['payment_id'] = payment_id = path[10]
828            dict['qs_dict'] = qs_dict = parse_qs(urlparsed[4])
829            tas.append(dict)
830            tr_count += 1
831        return tas
832    ###)
833
834    security.declareProtected(ModifyPortalContent,"importOnlinePaymentTransactions")###(
835    def importOnlinePaymentTransactions(self):
836        """load Online Payment Transactions from CSV values"""
837        import transaction
838        import random
839        #from pdb import set_trace
840        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
841        opt = self.online_payments_import
842        students_folder = self.portal_url.getPortalObject().campus.students
843        start = True
844        tr_count = 1
845        total = 0
846        #name = 'pume_results'
847        name = 'OnlineTransactions'
848        no_import = []
849        imported = []
850        logger = logging.getLogger('WAeUPTool.importOnlinePaymentTransactions')
851        try:
852            transactions = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
853        except:
854            logger.error('Error reading %s.csv' % name)
855            return
856        for pay_transaction in transactions:
857            if start:
858                start = False
859                logger.info('Start loading from %s.csv' % name)
860                s = ','.join(['"%s"' % fn for fn in pay_transaction.keys()])
861                no_import.append('%s,"Error"' % s)
862                format = ','.join(['"%%(%s)s"' % fn for fn in pay_transaction.keys()])
863                format_error = format + ',"%(Error)s"'
864            data = {}
865
866            # format of the first file sent by Tayo
867            #data['datetime'] = date = DateTime.DateTime(pay_transaction['Date'])
868            #data['student_id'] = student_id = pay_transaction['Payer ID']
869            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
870            #data['response_code'] = response_code = pay_transaction['Resp Code']
871            #data['amount'] = amount = pay_transaction['Amount']
872
873            # format of the second file sent by Tayo
874            #data['datetime'] = date = 0
875            #data['student_id'] = student_id = pay_transaction['Payer ID']
876            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
877            #data['response_code'] = response_code = '00'
878            #data['amount'] = amount = pay_transaction['Amount']
879
880            # format of the third file sent by Kehinde
881            data['datetime'] = date = 0
882            data['student_id'] = student_id = pay_transaction['customer_id']
883            data['order_id'] = order_id = pay_transaction['merchant_reference']
884            data['response_code'] = response_code = '00'
885            data['amount'] = amount = pay_transaction['Amount']
886
887            dup = False
888            if response_code == "12":
889                continue
890            try:
891                opt.addRecord(**data)
892            except ValueError:
893                dup = True
894            #from pdb import set_trace;set_trace()
895            if dup:
896                if response_code == "00":
897                    try:
898                        opt.modifyRecord(**data)
899                    except:
900                        logger.info("duplicate uid, order_id %(order_id)s, student_id %(student_id)s, response_code %(response_code)s" % data)
901                        continue
902                else:
903                    pay_transaction['Error'] = "Duplicate order_id"
904                    no_import.append( format_error % pay_transaction)
905                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
906                    continue
907            tr_count += 1
908            if tr_count > 1000:
909                if len(no_import) > 0:
910                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
911                             '\n'.join(no_import) + '\n')
912                    no_import = []
913                em = '%d transactions committed\n' % (tr_count)
914                transaction.commit()
915                regs = []
916                logger.info(em)
917                total += tr_count
918                tr_count = 0
919        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
920                                                '\n'.join(no_import))
921        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
922    ###)
923
924    security.declareProtected(ModifyPortalContent,'mass_create_faculty') ###(
925    def mass_create_faculty(self,mapping):
926        "create a faculty"
927        logger = logging.getLogger('WAeUPTool.mass_create_faculty')
928        academics_folder = self.portal_url.getPortalObject().campus.academics
929        fid = mapping['code']
930        if getattr(academics_folder,fid,None) is not None:
931            return '', "Faculty with ID: %s exists" % fid
932        logger.info('Creating Faculty %(code)s, %(title)s' % mapping)
933        try:
934            academics_folder.invokeFactory('Faculty', fid)
935        except BadRequest,E:
936            return '', "%s" % E
937        f = getattr(academics_folder,fid,None)
938        f.getContent().edit(mapping=mapping)
939        return fid,''
940    ###)
941
942    security.declareProtected(ModifyPortalContent,'mass_edit_faculty') ###(
943    def mass_edit_faculty(self,mapping):
944        "edit a faculty"
945        logger = logging.getLogger('WAeUPTool.mass_edit_faculty')
946        academics_folder = self.portal_url.getPortalObject().campus.academics
947        fid = mapping['code']
948        f = getattr(academics_folder,fid,None)
949        if f is None:
950            return '', "Faculty with ID: %s does not exist" % fid
951        logger.info('Editing Faculty %(code)s, %(title)s' % mapping)
952        f.getContent().edit(mapping=mapping)
953        return fid,''
954    ###)
955
956    security.declareProtected(ModifyPortalContent,'mass_create_department') ###(
957    def mass_create_department(self,mapping):
958        "create a department in the correct faculty"
959        logger = logging.getLogger('WAeUPTool.mass_create_department')
960        fid = mapping['faculty_code']
961        if getattr(self,'_v_faculties',None) is None:
962            res = self.portal_catalog(portal_type = "Faculty")
963            self._v_faculties = {}
964            for f in res:
965                self._v_faculties[f.getId] = f.getObject()
966        f = self._v_faculties.get(fid,None)
967        if f is None:
968            return '', "No Faculty with ID: %s" % fid
969        else:
970            did = mapping.get('code')
971            d = getattr(f,did,None)
972            if d is None or d.portal_type == "Faculty":
973                logger.info('Creating Department %(code)s, %(title)s' % mapping)
974                try:
975                    f.invokeFactory('Department', did)
976                except BadRequest,E:
977                    return '', "%s" % E
978                d = getattr(f,did)
979                d.invokeFactory('CoursesFolder','courses')
980                courses = getattr(d,'courses')
981                dict = {'Title': 'Courses'}
982                courses.getContent().edit(mapping=dict)
983                d.invokeFactory('CertificatesFolder','certificates')
984                certificates = getattr(d,'certificates')
985                dict = {'Title': 'Certificates'}
986                certificates.getContent().edit(mapping=dict)
987            d.getContent().edit(mapping=mapping)
988        return did,''
989    ###)
990
991    security.declareProtected(ModifyPortalContent,'mass_edit_department') ###(
992    def mass_edit_department(self,mapping):
993        "create a department in the correct faculty"
994        logger = logging.getLogger('WAeUPTool.mass_create_department')
995        academics_folder = self.portal_url.getPortalObject().campus.academics
996        fid = mapping['faculty_code']
997        did = mapping.get('code')
998        try:
999            d = getattr(getattr(academics_folder,fid),did,None)
1000        except KeyError:
1001            return '', "Department %s or Faculty %s wrong" % (did,fid)
1002        else:
1003            if d is None or d.portal_type == "Faculty":
1004                logger.info('Editing Department %(code)s, %(title)s' % mapping)
1005            d.getContent().edit(mapping=mapping)
1006        return did,''
1007    ###)
1008
1009    security.declareProtected(ModifyPortalContent,'mass_create_course') ###(
1010    def mass_create_course(self,mapping):
1011        #import pdb;pdb.set_trace()
1012        if getattr(self,'_v_course_list',None) is None:
1013            self._v_course_list = []
1014        if getattr(self,'_v_departments',None) is None:
1015            res = self.portal_catalog(portal_type = "Department")
1016            self._v_department_courses = {}
1017            for d in res:
1018                self._v_department_courses[d.getId] = getattr(d.getObject(),"courses",None)
1019        did = mapping['department_code']
1020        d = self._v_department_courses.get(did,None)
1021        if d is None:
1022            return '', "No Department with ID: %s" % did
1023        course_id = mapping.get('code')
1024        if course_id in self._v_course_list:
1025            return '', "Duplicate Course ID: %s" % did
1026        c = getattr(d,course_id,None)
1027        if c is not None:
1028            return '', "Duplicate Course ID: %s" % did
1029        try:
1030            d.invokeFactory('Course', course_id)
1031        except BadRequest,E:
1032            return '', "%s" % E
1033        self._v_course_list.append(course_id)
1034        c = getattr(d,course_id)
1035        c.getContent().edit(mapping=mapping)
1036        return course_id,''
1037    ###)
1038
1039    security.declareProtected(ModifyPortalContent,'mass_edit_course') ###(
1040    def mass_edit_course(self,mapping):
1041        #import pdb;pdb.set_trace()
1042        course_id = mapping.get('code')
1043        res = self.portal_catalog(id=course_id)
1044        if not res:
1045            return '', "No Course with ID: %s" % course_id
1046        c = res[0].getObject()
1047        c.getContent().edit(mapping=mapping)
1048        return course_id,''
1049    ###)
1050
1051    security.declareProtected(ModifyPortalContent,'mass_create_certificate') ###(
1052    def mass_create_certificate(self,mapping):
1053        if getattr(self,'_v_certificate_list',None) is None:
1054            self._v_certificate_list = []
1055        if getattr(self,'_v_department_certificates',None) is None:
1056            res = self.portal_catalog(portal_type = "Department")
1057            self._v_department_certificates = {}
1058            for d in res:
1059                self._v_department_certificates[d.getId] = getattr(d.getObject(),"certificates",None)
1060        did = mapping['department_code']
1061        d = self._v_department_certificates.get(did,None)
1062        if d is None:
1063            return '', "No Department with ID: %s" % did
1064        certificate_id = mapping.get('code')
1065        if certificate_id in self._v_certificate_list:
1066            return '', "Duplicate Certificate ID: %s" % did
1067        c = getattr(d,certificate_id,None)
1068        if c is not None:
1069            return '', "Duplicate Certificate ID: %s" % did
1070        try:
1071            d.invokeFactory('Certificate', certificate_id)
1072        except BadRequest,E:
1073            return '', "%s" % E
1074        self._v_certificate_list.append(certificate_id)
1075        c = getattr(d,certificate_id)
1076        c.getContent().edit(mapping=mapping)
1077        return certificate_id,''
1078    ###)
1079
1080    security.declareProtected(ModifyPortalContent,'mass_edit_certificate') ###(
1081    def mass_edit_certificate(self,mapping):
1082        #import pdb;pdb.set_trace()
1083        certificate_id = mapping.get('code')
1084        res = self.portal_catalog(id=certificate_id)
1085        if not res:
1086            return '', "No Certificate with ID: %s" % did
1087        c = res[0].getObject()
1088        c.getContent().edit(mapping=mapping)
1089        return certificate_id,''
1090    ###)
1091
1092    security.declareProtected(ModifyPortalContent,'mass_create_certificate_course') ###(
1093    def mass_create_certificate_course(self,mapping):
1094        if getattr(self,'_v_courses',None) is None:
1095            res = self.courses_catalog()
1096            self._v_courses= [course.code for course in res]
1097        if getattr(self,'_v_ceritficates',None) is None:
1098            res = self.portal_catalog(portal_type = "Certificate")
1099            self._v_certificates = {}
1100            for cert in res:
1101                self._v_certificates[cert.getId] = cert.getObject()
1102        certificate_course_id = mapping.get('code')
1103        if certificate_course_id not in self._v_courses:
1104            return '', "No Course with ID: %s" % certificate_course_id
1105        cert_id = mapping['certificate_code']
1106        cert = self._v_certificates.get(cert_id,None)
1107        if cert is None:
1108            return '', "No Certificate with ID: %s" % cert_id
1109        level_id = mapping.get('level')
1110        level = getattr(cert,level_id,None)
1111        if level is None:
1112            cert.invokeFactory('StudyLevel', level_id)
1113            level = getattr(cert,level_id,None)
1114        elif hasattr(level,certificate_course_id):
1115            return '', "Duplicate CertificateCourse ID: %s in %s/ %s" %\
1116            (certificate_course_id,cert_id,level_id)
1117        level.invokeFactory('CertificateCourse', certificate_course_id)
1118        c = getattr(level,certificate_course_id)
1119        c.getContent().edit(mapping=mapping)
1120        return certificate_course_id,''
1121    ###)
1122
1123    field2types_student = {   ###(
1124                      'StudentApplication':
1125                          {'id': 'application',
1126                           'title': 'Application Data',
1127                           'wf_transition_return': 'close',
1128                           'wf_transition_admit': 'remain',
1129                           'fields':
1130                             ('jamb_reg_no',
1131                              'entry_mode',
1132                              'entry_session',
1133                              'jamb_score',
1134                              'app_email',
1135                              'jamb_age',
1136                              #'jamb_state',
1137                              #'jamb_lga',
1138                              )
1139                              },
1140                      #'StudentPume':
1141                      #    {'id': 'pume',
1142                      #     'title': 'Pume Data',
1143                      #     'wf_transition_return': 'close',
1144                      #     'wf_transition_admit': 'close',
1145                      #     'fields':
1146                      #       ('pume_score',
1147                      #        )
1148                      #        },
1149                      'StudentClearance':
1150                          {'id': 'clearance',
1151                           'title': 'Clearance/Eligibility Record',
1152                           'wf_transition_return': 'close',
1153                           'wf_transition_admit': 'remain',
1154                           'fields':
1155                             ('matric_no',
1156                              'nationality',
1157                              'lga',
1158                              'birthday',
1159                              )
1160                              },
1161                         'StudentPersonal':
1162                          {'id': 'personal',
1163                           'title': 'Personal Data',
1164                           'wf_transition_return': 'open',
1165                           'wf_transition_admit': 'remain',
1166                           'fields':
1167                             ('firstname',
1168                              'middlename',
1169                              'lastname',
1170                              'sex',
1171                              'email',
1172                              'phone',
1173                              'perm_address',
1174                              )
1175                              },
1176                         'StudentStudyCourse':
1177                          {'id': 'study_course',
1178                           'title': 'Study Course',
1179                           'wf_transition_return': 'open',
1180                           'wf_transition_admit': 'remain',
1181                           'fields':
1182                             ('study_course',
1183                              'current_level',
1184                              'current_session',
1185                              'current_mode',
1186                              'current_verdict',
1187                              )
1188                              },
1189
1190                         'PaymentsFolder':
1191                          {'id': 'payments',
1192                           'title': 'Payments',
1193                           'wf_transition_return': 'open',
1194                           'wf_transition_admit': 'open',
1195                           'fields':
1196                             ()
1197                              },
1198                         }
1199    ###)
1200
1201    security.declareProtected(ModifyPortalContent,'mass_create_student') ###(
1202    def mass_create_student(self,mapping):
1203        "create a students record due import"
1204        logger = logging.getLogger('WAeUPTool.mass_create_student')
1205        students_folder = self.portal_url.getPortalObject().campus.students
1206        jamb_reg_no = mapping.get('jamb_reg_no',None)
1207        if jamb_reg_no:
1208            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1209            if res:
1210                return '',"jamb_reg_no exists"
1211        matric_no = mapping.get('matric_no',None)
1212        if matric_no:
1213            res = self.students_catalog(matric_no = matric_no)
1214            if res:
1215                return '',"matric_no exists"
1216        sid = self.waeup_tool.generateStudentId('?')
1217        students_folder.invokeFactory('Student', sid)
1218        student_obj = getattr(students_folder,sid)
1219        f2t = self.field2types_student
1220        d = {}
1221        d['jamb_sex']  = 'M'
1222        if mapping.get('sex'):
1223            d['jamb_sex']  = 'F'
1224        transition = mapping.get('reg_transition','admit')
1225        if transition not in ('admit','return'):
1226            return '',"no valid transition provided"
1227        for pt in f2t.keys():
1228            student_obj.invokeFactory(pt,f2t[pt]['id'])
1229            sub_obj = getattr(student_obj,f2t[pt]['id'])
1230            sub_doc = sub_obj.getContent()
1231            d['Title'] = f2t[pt]['title']
1232            for field in f2t[pt]['fields']:
1233                d[field] = mapping.get(field,'')
1234            if pt == "StudyCourse":
1235                for von,zu in (('entry_mode','current_mode'),
1236                               ('entry_session','current_session')):
1237                    if mapping.get(zu,None) is None and mapping.get(von,None) is not None:
1238                        d[zu] = mapping[von]
1239            sub_doc.edit(mapping = d)
1240
1241            #import pdb;pdb.set_trace()
1242            new_state = f2t[pt]['wf_transition_%(transition)s' % vars()]
1243            if new_state != "remain":
1244                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1245        self.portal_workflow.doActionFor(student_obj,transition)
1246        student_obj.manage_setLocalRoles(sid, ['Owner',])
1247        return sid,''
1248    ###)
1249
1250    security.declareProtected(ModifyPortalContent,'mass_edit_student') ###(
1251    def mass_edit_student(self,mapping):
1252        "edit a students record due import"
1253        logger = logging.getLogger('WAeUPTool.mass_edit_student')
1254        students_folder = self.portal_url.getPortalObject().campus.students
1255        sid = mapping.get('id',None)
1256        jamb_reg_no = mapping.get('jamb_reg_no',None)
1257        matric_no = mapping.get('matric_no',None)
1258        editable_keys = mapping.keys()
1259        if sid:
1260            res = self.students_catalog(id = sid)
1261            if not res:
1262                return '',"no student with id %s" % sid
1263            if matric_no and res[0].matric_no and\
1264              matric_no != res[0].matric_no:
1265                logger.info("%s, old matric_no %s overwritten with %s" % (res[0].id,res[0].matric_no,matric_no))
1266            if jamb_reg_no and res[0].jamb_reg_no and\
1267              jamb_reg_no != res[0].jamb_reg_no:
1268                logger.info("%s, old reg_no %s overwritten with %s" % (res[0].id,res[0].jamb_reg_no,jamb_reg_no))
1269        elif jamb_reg_no:
1270            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1271            if not res:
1272                return '',"no student with jamb_reg_no %s" % jamb_reg_no
1273            editable_keys.remove('jamb_reg_no')
1274        elif matric_no:
1275            res = self.students_catalog(matric_no = matric_no)
1276            if not res:
1277                return '',"no student with matric_no %s" % matric_no
1278            editable_keys.remove('matric_no')
1279
1280        ## included only to change wf state from admitted to returning
1281        #if res[0].review_state not in ('admitted','objection_raised'):
1282        #    return '%s' % res[0].id ,"student is not in state admitted or objection_raised"
1283        ## end inclusion
1284
1285        sid = res[0].id
1286        student_obj = getattr(students_folder,sid)
1287        f2t = self.field2types_student
1288        d = {}
1289        #import pdb;pdb.set_trace()
1290        any_change = False
1291        for pt in f2t.keys():
1292            if pt == "student_application":
1293                d['jamb_sex']  = 'M'
1294                if mapping.get('sex'):
1295                    d['jamb_sex']  = 'F'
1296            intersect = set(f2t[pt]['fields']).intersection(set(editable_keys))
1297            if intersect:
1298                sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1299                if sub_obj is None:
1300                    try:
1301                        student_obj.invokeFactory(pt,f2t[pt]['id'])
1302                    except:
1303                        continue
1304                    sub_obj = getattr(student_obj,f2t[pt]['id'])
1305                    d['Title'] = f2t[pt]['title']
1306                sub_doc = sub_obj.getContent()
1307                for field in intersect:
1308                    changed = False
1309                    if getattr(sub_doc,field) != mapping.get(field,''):
1310                        any_change = True
1311                        changed = True
1312                        d[field] = mapping.get(field,'')
1313                    if changed:
1314                        sub_doc.edit(mapping = d)
1315
1316
1317        ## included only to change wf state from admitted to returning
1318        #    if res[0].review_state in ('admitted','objection_raised'):
1319        #        new_state = f2t[pt]['wf_transition_return']
1320        #        sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1321        #        if sub_obj and new_state != "remain":
1322        #            try:
1323        #                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1324        #            except:
1325        #                #logger.info('%s, wf transition %s of %s failed' % (sid,new_state,sub_obj.id))
1326        #                pass
1327        #if res[0].review_state in ('admitted','objection_raised'):
1328        #    wfaction = 'return'
1329        #    try:
1330        #        self.portal_workflow.doActionFor(student_obj,wfaction)
1331        #        logger.info('%s, wf state changed' % sid)
1332        #        any_change = True
1333        #    except:
1334        #        logger.info('%s, wf transition failed, old state = %s' % (sid,res[0].review_state))
1335        #        pass
1336        ## end inclusion
1337
1338
1339        if any_change:
1340            return sid,''
1341        else:
1342            return sid,'not modified'
1343    ###)
1344
1345    security.declareProtected(ModifyPortalContent,"importData")###(
1346    def importData(self,filename,name,edit=False,bypass_queue_catalog=False):
1347        """load data from CSV values"""
1348        import transaction
1349        import random
1350
1351        pm = self.portal_membership
1352        member = pm.getAuthenticatedMember()
1353
1354        logger = logging.getLogger('WAeUPTool.importData')
1355        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1356        students_folder = self.portal_url.getPortalObject().campus.students
1357        start = True
1358        tr_count = 1
1359        total_imported = 0
1360        total_not_imported = 0
1361        total = 0
1362        iname = "import_%s" % name
1363        stool = getToolByName(self, 'portal_schemas')
1364        ltool = getToolByName(self, 'portal_layouts')
1365        schema = stool._getOb(iname)
1366        if schema is None:
1367            em = 'No such schema %s' % iname
1368            logger.error('No such schema %s' % iname)
1369            return em
1370        layout = ltool._getOb(iname)
1371        if layout is None:
1372            em = 'No such layout %s' % iname
1373            logger.error(em)
1374            return em
1375        validators = {}
1376        for widget in layout.keys():
1377            validators[widget] = layout[widget].validate
1378        #import pdb;pdb.set_trace()
1379        mode = "create"
1380        if edit:
1381            mode = "edit"
1382        importer_name = "mass_%(mode)s_%(name)s" % vars()
1383        importer = getattr(self, '%s' % importer_name,None)
1384        if importer is None:
1385            em = 'No importer function %s' % importer_name
1386            logger.error(em)
1387            return em
1388        not_imported = []
1389        imported = []
1390        try:
1391            items = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
1392        except:
1393            em = 'Error reading %s.csv' % filename
1394            logger.error(em)
1395            return em
1396        for item in items:
1397            if start:
1398                start = False
1399                adapters = [MappingStorageAdapter(schema, item)]
1400                logger.info('%s starts import from %s.csv in %s mode with schema and layout %s' % (member,filename,mode,iname))
1401                attrs = csv.reader(open("%s/import/%s.csv" % (i_home,filename),"rb")).next()
1402                import_keys = [k for k in attrs if not k.startswith('ignore')]
1403                diff2schema = set(import_keys).difference(set(schema.keys()))
1404                diff2layout = set(import_keys).difference(set(layout.keys()))
1405                if diff2schema:
1406                    em = 'not ignorable key(s): "%s" found in heading' % ", ".join(diff2schema)
1407                    return em
1408                s = ','.join(['"%s"' % fn for fn in import_keys])
1409                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(s + ',"Error"'+ '\n')
1410                s = '"id",' + s
1411                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
1412                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
1413                format_error = format + ',"%(Error)s"'
1414                format = '"%(id)s",'+ format
1415
1416            dm = DataModel(item, adapters,context=self)
1417            ds = DataStructure(data=item,datamodel=dm)
1418            error_string = ""
1419            for k in import_keys:
1420                #import pdb;pdb.set_trace()
1421                if not validators[k](ds,mode=mode):
1422                    error_string += " %s : %s" % (k,
1423                                                  self.translation_service(ds.getError(k),
1424                                                                           ds.getErrorMapping(k)))
1425            if not error_string:
1426                item.update(dm)
1427                item['id'],error = importer(item)
1428                if error:
1429                    error_string += error
1430            if error_string:
1431                item['Error'] = error_string
1432                not_imported.append(format_error % item)
1433                total_not_imported += 1
1434            else:
1435                em = format % item
1436                imported.append(em)
1437                logger.info("%(total_imported)d of %(total)d %(em)s" % vars())
1438                tr_count += 1
1439                total_imported += 1
1440            total += 1
1441            if total and not total % 100:
1442                transaction.commit()
1443                if len(not_imported) > 0:
1444                    open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1445                             '\n'.join(not_imported) + '\n')
1446                    not_imported = []
1447                if len(imported) > 0:
1448                    open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
1449                             '\n'.join(imported) + '\n')
1450                    imported = []
1451                em = '%d transactions committed\n' % (tr_count)
1452                regs = []
1453                logger.info(em)
1454                tr_count = 0
1455        if len(imported) > 0:
1456            open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
1457                                                '\n'.join(imported))
1458        if len(not_imported) > 0:
1459            open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1460                                                '\n'.join(not_imported))
1461        em = "Imported: %d, not imported: %d of total %d" % (total_imported,total_not_imported,total)
1462        return em
1463    ###)
1464
1465    security.declareProtected(ModifyPortalContent,"moveImagesToFS")###(
1466    def moveImagesToFS(self,student_id="O738726"):
1467        "move the images to the filesystem"
1468        images_dir = os.path.join("%s/images" % i_home,student_id)
1469        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1470        stool = getToolByName(self, 'portal_schemas')
1471        schemas = ['student_application',
1472                   'student_clearance',
1473                   ]
1474        created = False
1475        for schema_id in schemas:
1476            schema = stool._getOb(schema_id)
1477            object = getattr(student_folder,schema_id[len('student_'):],None)
1478            if object is None:
1479                continue
1480            doc = object.getContent()
1481            for key in schema.keys():
1482                if schema[key].meta_type != "CPS Image Field":
1483                    continue
1484                #import pdb;pdb.set_trace()
1485                image = getattr(doc,key,None)
1486                if not image or not hasattr(image,"data"):
1487                    continue
1488                if not created:
1489                    if not os.path.exists(images_dir):
1490                        os.mkdir(images_dir)
1491                    created = True
1492                filename = os.path.join(images_dir,"%(key)s_%(student_id)s.jpg" % vars())
1493                open(filename,"wb").write(str(image.data))
1494
1495    security.declareProtected(ModifyPortalContent,"movePassportToFS")###(
1496    def movePassportToFS(self,student_id="O738726"):
1497        "move the passports to the filesystem"
1498        images_dir = os.path.join("%s" % i_home,'passports')
1499        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1500        stool = getToolByName(self, 'portal_schemas')
1501        schemas = ['student_application',
1502                   #'student_clearance',
1503                   ]
1504        created = False
1505        for schema_id in schemas:
1506            schema = stool._getOb(schema_id)
1507            object = getattr(student_folder,schema_id[len('student_'):],None)
1508            if object is None:
1509                continue
1510            doc = object.getContent()
1511            for key in schema.keys():
1512                if schema[key].meta_type != "CPS Image Field":
1513                    continue
1514                #import pdb;pdb.set_trace()
1515                image = getattr(doc,key)
1516                if not hasattr(image,"data"):
1517                    continue
1518                if not created:
1519                    if not os.path.exists(images_dir):
1520                        os.mkdir(images_dir)
1521                    created = True
1522                filename = os.path.join(images_dir,"%(student_id)s.jpg" % vars())
1523                open(filename,"wb").write(str(image.data))
1524
1525InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.