source: WAeUP_SRP/base/WAeUPTool.py @ 2344

Last change on this file since 2344 was 2342, checked in by joachim, 17 years ago

rename No Zodb Image Widget to Application Image Widget

  • Property svn:keywords set to Id
File size: 62.4 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 2342 2007-10-10 15:43:43Z 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        if os.path.exists(picture_path):
699            response.setHeader('Content-type','image/jpeg')
700            return open(picture_path).read()
701        picture_path = os.path.join(i_home,'import',path)
702        if os.path.exists(picture_path):
703            return open(picture_path).read()
704       
705
706    ###)
707
708    security.declareProtected(ModifyPortalContent,'deleteAllCourses') ###(
709    def deleteAllCourses(self,department="All"):
710        ''' delete the courses'''
711        pm = self.portal_membership
712        member = pm.getAuthenticatedMember()
713
714        if str(member) not in ("henrik","joachim"):
715            return "not possible"
716        if department == "All":
717            res = self.portal_catalog({'meta_type': 'Department'})
718        if len(res) < 1:
719            return "No Departments found"
720
721        deleted = []
722        for dep in res:
723            cf = dep.getObject().courses
724            if cf:
725                cf.manage_delObjects(ids=cf.objectIds())
726                deleted.append("deleted Courses in %s" % dep.getId)
727        return "\r".join(deleted)
728    ###)
729
730    security.declareProtected(ModifyPortalContent,'getLogfileLines') ###(
731    def getLogfileLines(self,filename="event.log",numlines=20):
732        """Get last NUMLINES lines of logfile FILENAME.
733
734        Return last lines' of a file in the instances logfile directory as
735        a list. The number of returned lines equals `numlines' or less. If
736        less than `numlines' lines are available, the whole file ist
737        returned. If the file can not be opened or some other error
738        occurs, empty list is returend.
739        """
740        result = []
741        lines_hit = 0
742
743        # We only handle files in instances' log directory...
744        logpath = os.path.join(i_home, "log")
745        filename = str(os.path.abspath( os.path.join( logpath, filename )))
746        if not filename.startswith( logpath ):
747            # Attempt to access file outside log-dir...
748            return []
749
750        try:
751            fd = file( filename, "rb" )
752        except IOError:
753            return []
754        if not fd:
755            return []
756
757        if os.linesep == None:
758            linesep = '\n'
759        else:
760            linesep = os.linesep
761
762        # Try to find 'numlines' times a lineseparator, searching from end
763        # and moving to the beginning of file...
764        fd.seek( 0, 2) # Move to end of file...
765        while lines_hit < numlines:
766            if fd.read(1) == linesep[-1]: # This moves filedescriptor
767                                          # one step forward...
768                lines_hit += 1
769            try:
770                fd.seek( -2, 1) # Go two bytes back from current pos...
771            except IOError:
772                # We cannot go back two bytes. Maybe the file is too small...
773                break
774        fd.seek(2,1)
775
776        # Read all lines from current position...
777        result = fd.readlines()
778        # Remove line endings...
779        result = [x.strip() for x in result]
780        fd.close()
781        return result
782    ###)
783
784    security.declareProtected(ModifyPortalContent,"getCallbacksFromLog")###(
785    def getCallbacksFromLog(self,filename):
786        """fix Online Payment Transactions from Z2.log entries"""
787        import transaction
788        import random
789        from cgi import parse_qs
790        from urlparse import urlparse
791        #from pdb import set_trace
792        wftool = self.portal_workflow
793        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
794        students_folder = self.portal_url.getPortalObject().campus.students
795        s = r'(?P<client_ip>\S+) - (?P<member_id>\S+) \['
796        s += r'(?P<date>.*)\] "(?P<get>.*)" (?P<codes>\d+ \d+) "'
797        s += r'(?P<intersw>.*)" "(?P<agent>.*)"'
798        data = re.compile(s)
799        start = True
800        tr_count = 1
801        total = 0
802        #name = 'pume_results'
803        #name = 'epaymentsuccessful_z2log2'
804        name = filename
805        no_import = []
806        imported = []
807        logger = logging.getLogger('WAeUPTool.getFailedTransactions')
808        try:
809            transactions = open("%s/import/%s" % (i_home,name),"rb").readlines()
810        except:
811            logger.error('Error reading %s' % name)
812            return
813        tas = []
814        for line in transactions:
815            dict = {}
816            items = data.search(line)
817            dict['idict'] = idict = items.groupdict()
818            #print idict
819            #from pdb import set_trace;set_trace()
820            urlparsed = urlparse(idict['get'][4:])
821            #print urlparsed
822            path = urlparsed[2].split('/')
823            dict['student_id'] = student_id = path[8]
824            dict['payment_id'] = payment_id = path[10]
825            dict['qs_dict'] = qs_dict = parse_qs(urlparsed[4])
826            tas.append(dict)
827            tr_count += 1
828        return tas
829    ###)
830
831    security.declareProtected(ModifyPortalContent,"importOnlinePaymentTransactions")###(
832    def importOnlinePaymentTransactions(self):
833        """load Online Payment Transactions from CSV values"""
834        import transaction
835        import random
836        #from pdb import set_trace
837        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
838        opt = self.online_payments_import
839        students_folder = self.portal_url.getPortalObject().campus.students
840        start = True
841        tr_count = 1
842        total = 0
843        #name = 'pume_results'
844        name = 'OnlineTransactions'
845        no_import = []
846        imported = []
847        logger = logging.getLogger('WAeUPTool.importOnlinePaymentTransactions')
848        try:
849            transactions = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
850        except:
851            logger.error('Error reading %s.csv' % name)
852            return
853        for pay_transaction in transactions:
854            if start:
855                start = False
856                logger.info('Start loading from %s.csv' % name)
857                s = ','.join(['"%s"' % fn for fn in pay_transaction.keys()])
858                no_import.append('%s,"Error"' % s)
859                format = ','.join(['"%%(%s)s"' % fn for fn in pay_transaction.keys()])
860                format_error = format + ',"%(Error)s"'
861            data = {}
862
863            # format of the first file sent by Tayo
864            #data['datetime'] = date = DateTime.DateTime(pay_transaction['Date'])
865            #data['student_id'] = student_id = pay_transaction['Payer ID']
866            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
867            #data['response_code'] = response_code = pay_transaction['Resp Code']
868            #data['amount'] = amount = pay_transaction['Amount']
869
870            # format of the second file sent by Tayo
871            #data['datetime'] = date = 0
872            #data['student_id'] = student_id = pay_transaction['Payer ID']
873            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
874            #data['response_code'] = response_code = '00'
875            #data['amount'] = amount = pay_transaction['Amount']
876
877            # format of the third file sent by Kehinde
878            data['datetime'] = date = 0
879            data['student_id'] = student_id = pay_transaction['customer_id']
880            data['order_id'] = order_id = pay_transaction['merchant_reference']
881            data['response_code'] = response_code = '00'
882            data['amount'] = amount = pay_transaction['Amount']
883
884            dup = False
885            if response_code == "12":
886                continue
887            try:
888                opt.addRecord(**data)
889            except ValueError:
890                dup = True
891            #from pdb import set_trace;set_trace()
892            if dup:
893                if response_code == "00":
894                    try:
895                        opt.modifyRecord(**data)
896                    except:
897                        logger.info("duplicate uid, order_id %(order_id)s, student_id %(student_id)s, response_code %(response_code)s" % data)
898                        continue
899                else:
900                    pay_transaction['Error'] = "Duplicate order_id"
901                    no_import.append( format_error % pay_transaction)
902                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
903                    continue
904            tr_count += 1
905            if tr_count > 1000:
906                if len(no_import) > 0:
907                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
908                             '\n'.join(no_import) + '\n')
909                    no_import = []
910                em = '%d transactions committed\n' % (tr_count)
911                transaction.commit()
912                regs = []
913                logger.info(em)
914                total += tr_count
915                tr_count = 0
916        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
917                                                '\n'.join(no_import))
918        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
919    ###)
920
921    security.declareProtected(ModifyPortalContent,'mass_create_faculty') ###(
922    def mass_create_faculty(self,mapping):
923        "create a faculty"
924        logger = logging.getLogger('WAeUPTool.mass_create_faculty')
925        academics_folder = self.portal_url.getPortalObject().campus.academics
926        fid = mapping['code']
927        if getattr(academics_folder,fid,None) is not None:
928            return '', "Faculty with ID: %s exists" % fid
929        logger.info('Creating Faculty %(code)s, %(title)s' % mapping)
930        try:
931            academics_folder.invokeFactory('Faculty', fid)
932        except BadRequest,E:
933            return '', "%s" % E
934        f = getattr(academics_folder,fid,None)
935        f.getContent().edit(mapping=mapping)
936        return fid,''
937    ###)
938
939    security.declareProtected(ModifyPortalContent,'mass_edit_faculty') ###(
940    def mass_edit_faculty(self,mapping):
941        "edit a faculty"
942        logger = logging.getLogger('WAeUPTool.mass_edit_faculty')
943        academics_folder = self.portal_url.getPortalObject().campus.academics
944        fid = mapping['code']
945        f = getattr(academics_folder,fid,None)
946        if f is None:
947            return '', "Faculty with ID: %s does not exist" % fid
948        logger.info('Editing Faculty %(code)s, %(title)s' % mapping)
949        f.getContent().edit(mapping=mapping)
950        return fid,''
951    ###)
952
953    security.declareProtected(ModifyPortalContent,'mass_create_department') ###(
954    def mass_create_department(self,mapping):
955        "create a department in the correct faculty"
956        logger = logging.getLogger('WAeUPTool.mass_create_department')
957        fid = mapping['faculty_code']
958        if getattr(self,'_v_faculties',None) is None:
959            res = self.portal_catalog(portal_type = "Faculty")
960            self._v_faculties = {}
961            for f in res:
962                self._v_faculties[f.getId] = f.getObject()
963        f = self._v_faculties.get(fid,None)
964        if f is None:
965            return '', "No Faculty with ID: %s" % fid
966        else:
967            did = mapping.get('code')
968            d = getattr(f,did,None)
969            if d is None or d.portal_type == "Faculty":
970                logger.info('Creating Department %(code)s, %(title)s' % mapping)
971                try:
972                    f.invokeFactory('Department', did)
973                except BadRequest,E:
974                    return '', "%s" % E
975                d = getattr(f,did)
976                d.invokeFactory('CoursesFolder','courses')
977                courses = getattr(d,'courses')
978                dict = {'Title': 'Courses'}
979                courses.getContent().edit(mapping=dict)
980                d.invokeFactory('CertificatesFolder','certificates')
981                certificates = getattr(d,'certificates')
982                dict = {'Title': 'Certificates'}
983                certificates.getContent().edit(mapping=dict)
984            d.getContent().edit(mapping=mapping)
985        return did,''
986    ###)
987
988    security.declareProtected(ModifyPortalContent,'mass_edit_department') ###(
989    def mass_edit_department(self,mapping):
990        "create a department in the correct faculty"
991        logger = logging.getLogger('WAeUPTool.mass_create_department')
992        academics_folder = self.portal_url.getPortalObject().campus.academics
993        fid = mapping['faculty_code']
994        did = mapping.get('code')
995        try:
996            d = getattr(getattr(academics_folder,fid),did,None)
997        except KeyError:
998            return '', "Department %s or Faculty %s wrong" % (did,fid)
999        else:
1000            if d is None or d.portal_type == "Faculty":
1001                logger.info('Editing Department %(code)s, %(title)s' % mapping)
1002            d.getContent().edit(mapping=mapping)
1003        return did,''
1004    ###)
1005
1006    security.declareProtected(ModifyPortalContent,'mass_create_course') ###(
1007    def mass_create_course(self,mapping):
1008        #import pdb;pdb.set_trace()
1009        if getattr(self,'_v_course_list',None) is None:
1010            self._v_course_list = []
1011        if getattr(self,'_v_departments',None) is None:
1012            res = self.portal_catalog(portal_type = "Department")
1013            self._v_department_courses = {}
1014            for d in res:
1015                self._v_department_courses[d.getId] = getattr(d.getObject(),"courses",None)
1016        did = mapping['department_code']
1017        d = self._v_department_courses.get(did,None)
1018        if d is None:
1019            return '', "No Department with ID: %s" % did
1020        course_id = mapping.get('code')
1021        if course_id in self._v_course_list:
1022            return '', "Duplicate Course ID: %s" % did
1023        c = getattr(d,course_id,None)
1024        if c is not None:
1025            return '', "Duplicate Course ID: %s" % did
1026        try:
1027            d.invokeFactory('Course', course_id)
1028        except BadRequest,E:
1029            return '', "%s" % E
1030        self._v_course_list.append(course_id)
1031        c = getattr(d,course_id)
1032        c.getContent().edit(mapping=mapping)
1033        return course_id,''
1034    ###)
1035
1036    security.declareProtected(ModifyPortalContent,'mass_edit_course') ###(
1037    def mass_edit_course(self,mapping):
1038        #import pdb;pdb.set_trace()
1039        course_id = mapping.get('code')
1040        res = self.portal_catalog(id=course_id)
1041        if not res:
1042            return '', "No Course with ID: %s" % course_id
1043        c = res[0].getObject()
1044        c.getContent().edit(mapping=mapping)
1045        return course_id,''
1046    ###)
1047
1048    security.declareProtected(ModifyPortalContent,'mass_create_certificate') ###(
1049    def mass_create_certificate(self,mapping):
1050        if getattr(self,'_v_certificate_list',None) is None:
1051            self._v_certificate_list = []
1052        if getattr(self,'_v_department_certificates',None) is None:
1053            res = self.portal_catalog(portal_type = "Department")
1054            self._v_department_certificates = {}
1055            for d in res:
1056                self._v_department_certificates[d.getId] = getattr(d.getObject(),"certificates",None)
1057        did = mapping['department_code']
1058        d = self._v_department_certificates.get(did,None)
1059        if d is None:
1060            return '', "No Department with ID: %s" % did
1061        certificate_id = mapping.get('code')
1062        if certificate_id in self._v_certificate_list:
1063            return '', "Duplicate Certificate ID: %s" % did
1064        c = getattr(d,certificate_id,None)
1065        if c is not None:
1066            return '', "Duplicate Certificate ID: %s" % did
1067        try:
1068            d.invokeFactory('Certificate', certificate_id)
1069        except BadRequest,E:
1070            return '', "%s" % E
1071        self._v_certificate_list.append(certificate_id)
1072        c = getattr(d,certificate_id)
1073        c.getContent().edit(mapping=mapping)
1074        return certificate_id,''
1075    ###)
1076
1077    security.declareProtected(ModifyPortalContent,'mass_edit_certificate') ###(
1078    def mass_edit_certificate(self,mapping):
1079        #import pdb;pdb.set_trace()
1080        certificate_id = mapping.get('code')
1081        res = self.portal_catalog(id=certificate_id)
1082        if not res:
1083            return '', "No Certificate with ID: %s" % did
1084        c = res[0].getObject()
1085        c.getContent().edit(mapping=mapping)
1086        return certificate_id,''
1087    ###)
1088
1089    security.declareProtected(ModifyPortalContent,'mass_create_certificate_course') ###(
1090    def mass_create_certificate_course(self,mapping):
1091        if getattr(self,'_v_courses',None) is None:
1092            res = self.courses_catalog()
1093            self._v_courses= [course.code for course in res] 
1094        if getattr(self,'_v_ceritficates',None) is None:
1095            res = self.portal_catalog(portal_type = "Certificate")
1096            self._v_certificates = {}
1097            for cert in res:
1098                self._v_certificates[cert.getId] = cert.getObject()
1099        certificate_course_id = mapping.get('code')
1100        if certificate_course_id not in self._v_courses:
1101            return '', "No Course with ID: %s" % certificate_course_id
1102        cert_id = mapping['certificate_code']
1103        cert = self._v_certificates.get(cert_id,None)
1104        if cert is None:
1105            return '', "No Certificate with ID: %s" % cert_id
1106        level_id = mapping.get('level')
1107        level = getattr(cert,level_id,None)
1108        if level is None:
1109            cert.invokeFactory('StudyLevel', level_id)
1110            level = getattr(cert,level_id,None)
1111        elif hasattr(level,certificate_course_id):
1112            return '', "Duplicate CertificateCourse ID: %s in %s/ %s" %\
1113            (certificate_course_id,cert_id,level_id)
1114        level.invokeFactory('CertificateCourse', certificate_course_id)
1115        c = getattr(level,certificate_course_id)
1116        c.getContent().edit(mapping=mapping)
1117        return certificate_course_id,''
1118    ###)
1119
1120    field2types_student = {   ###(
1121                      'StudentApplication':
1122                          {'id': 'application',
1123                           'title': 'Application Data',
1124                           'wf_transition_return': 'close',
1125                           'wf_transition_admit': 'remain',
1126                           'fields':
1127                             ('jamb_reg_no',
1128                              'entry_mode',
1129                              'entry_session',
1130                              'jamb_score',
1131                              'app_email',
1132                              'jamb_age',
1133                              #'jamb_state',
1134                              #'jamb_lga',
1135                              )
1136                              },
1137                      #'StudentPume':
1138                      #    {'id': 'pume',
1139                      #     'title': 'Pume Data',
1140                      #     'wf_transition_return': 'close',
1141                      #     'wf_transition_admit': 'close',
1142                      #     'fields':
1143                      #       ('pume_score',
1144                      #        )
1145                      #        },
1146                      'StudentClearance':
1147                          {'id': 'clearance',
1148                           'title': 'Clearance/Eligibility Record',
1149                           'wf_transition_return': 'close',
1150                           'wf_transition_admit': 'remain',
1151                           'fields':
1152                             ('matric_no',
1153                              'nationality',
1154                              'lga',
1155                              'birthday',
1156                              )
1157                              },
1158                         'StudentPersonal':
1159                          {'id': 'personal',
1160                           'title': 'Personal Data',
1161                           'wf_transition_return': 'open',
1162                           'wf_transition_admit': 'remain',
1163                           'fields':
1164                             ('firstname',
1165                              'middlename',
1166                              'lastname',
1167                              'sex',
1168                              'email',
1169                              'phone',
1170                              'perm_address',
1171                              )
1172                              },
1173                         'StudentStudyCourse':
1174                          {'id': 'study_course',
1175                           'title': 'Study Course',
1176                           'wf_transition_return': 'open',
1177                           'wf_transition_admit': 'remain',
1178                           'fields':
1179                             ('study_course',
1180                              'current_level',
1181                              'current_session',
1182                              'current_mode',
1183                              'current_verdict',
1184                              )
1185                              },
1186
1187                         'PaymentsFolder':
1188                          {'id': 'payments',
1189                           'title': 'Payments',
1190                           'wf_transition_return': 'open',
1191                           'wf_transition_admit': 'open',
1192                           'fields':
1193                             ()
1194                              },
1195                         }
1196    ###)
1197
1198    security.declareProtected(ModifyPortalContent,'mass_create_student') ###(
1199    def mass_create_student(self,mapping):
1200        "create a students record due import"
1201        logger = logging.getLogger('WAeUPTool.mass_create_student')
1202        students_folder = self.portal_url.getPortalObject().campus.students
1203        jamb_reg_no = mapping.get('jamb_reg_no',None)
1204        if jamb_reg_no:
1205            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1206            if res:
1207                return '',"jamb_reg_no exists"
1208        matric_no = mapping.get('matric_no',None)
1209        if matric_no:
1210            res = self.students_catalog(matric_no = matric_no)
1211            if res:
1212                return '',"matric_no exists"
1213        sid = self.waeup_tool.generateStudentId('?')
1214        students_folder.invokeFactory('Student', sid)
1215        student_obj = getattr(students_folder,sid)
1216        f2t = self.field2types_student
1217        d = {}
1218        d['jamb_sex']  = 'M'
1219        if mapping.get('sex'):
1220            d['jamb_sex']  = 'F'
1221        transition = mapping.get('reg_transition','admit')
1222        if transition not in ('admit','return'):
1223            return '',"no valid transition provided"
1224        for pt in f2t.keys():
1225            student_obj.invokeFactory(pt,f2t[pt]['id'])
1226            sub_obj = getattr(student_obj,f2t[pt]['id'])
1227            sub_doc = sub_obj.getContent()
1228            d['Title'] = f2t[pt]['title']
1229            for field in f2t[pt]['fields']:
1230                d[field] = mapping.get(field,'')
1231            if pt == "StudyCourse":
1232                for von,zu in (('entry_mode','current_mode'),
1233                               ('entry_session','current_session')):
1234                    if mapping.get(zu,None) is None and mapping.get(von,None) is not None:
1235                        d[zu] = mapping[von]
1236            sub_doc.edit(mapping = d)
1237
1238            #import pdb;pdb.set_trace()
1239            new_state = f2t[pt]['wf_transition_%(transition)s' % vars()]
1240            if new_state != "remain":
1241                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1242        self.portal_workflow.doActionFor(student_obj,transition)
1243        student_obj.manage_setLocalRoles(sid, ['Owner',])
1244        return sid,''
1245    ###)
1246
1247    security.declareProtected(ModifyPortalContent,'mass_edit_student') ###(
1248    def mass_edit_student(self,mapping):
1249        "edit a students record due import"
1250        logger = logging.getLogger('WAeUPTool.mass_edit_student')
1251        students_folder = self.portal_url.getPortalObject().campus.students
1252        sid = mapping.get('id',None)
1253        jamb_reg_no = mapping.get('jamb_reg_no',None)
1254        matric_no = mapping.get('matric_no',None)
1255        editable_keys = mapping.keys()
1256        if sid:
1257            res = self.students_catalog(id = sid)
1258            if not res:
1259                return '',"no student with id %s" % sid
1260            if matric_no and res[0].matric_no and\
1261              matric_no != res[0].matric_no:
1262                logger.info("%s, old matric_no %s overwritten with %s" % (res[0].id,res[0].matric_no,matric_no))
1263            if jamb_reg_no and res[0].jamb_reg_no and\
1264              jamb_reg_no != res[0].jamb_reg_no:
1265                logger.info("%s, old reg_no %s overwritten with %s" % (res[0].id,res[0].jamb_reg_no,jamb_reg_no))
1266        elif jamb_reg_no:
1267            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1268            if not res:
1269                return '',"no student with jamb_reg_no %s" % jamb_reg_no
1270            editable_keys.remove('jamb_reg_no')
1271        elif matric_no:
1272            res = self.students_catalog(matric_no = matric_no)
1273            if not res:
1274                return '',"no student with matric_no %s" % matric_no
1275            editable_keys.remove('matric_no')
1276
1277        ## included only to change wf state from admitted to returning
1278        #if res[0].review_state not in ('admitted','objection_raised'):
1279        #    return '%s' % res[0].id ,"student is not in state admitted or objection_raised"
1280        ## end inclusion
1281
1282        sid = res[0].id
1283        student_obj = getattr(students_folder,sid)
1284        f2t = self.field2types_student
1285        d = {}
1286        #import pdb;pdb.set_trace()
1287        any_change = False
1288        for pt in f2t.keys():
1289            if pt == "student_application":
1290                d['jamb_sex']  = 'M'
1291                if mapping.get('sex'):
1292                    d['jamb_sex']  = 'F'
1293            intersect = set(f2t[pt]['fields']).intersection(set(editable_keys))
1294            if intersect:
1295                sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1296                if sub_obj is None:
1297                    try:
1298                        student_obj.invokeFactory(pt,f2t[pt]['id'])
1299                    except:
1300                        continue
1301                    sub_obj = getattr(student_obj,f2t[pt]['id'])
1302                    d['Title'] = f2t[pt]['title']
1303                sub_doc = sub_obj.getContent()
1304                for field in intersect:
1305                    changed = False
1306                    if getattr(sub_doc,field) != mapping.get(field,''):
1307                        any_change = True
1308                        changed = True
1309                        d[field] = mapping.get(field,'')
1310                    if changed:
1311                        sub_doc.edit(mapping = d)
1312
1313
1314        ## included only to change wf state from admitted to returning
1315        #    if res[0].review_state in ('admitted','objection_raised'):
1316        #        new_state = f2t[pt]['wf_transition_return']
1317        #        sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1318        #        if sub_obj and new_state != "remain":
1319        #            try:
1320        #                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1321        #            except:
1322        #                #logger.info('%s, wf transition %s of %s failed' % (sid,new_state,sub_obj.id))
1323        #                pass
1324        #if res[0].review_state in ('admitted','objection_raised'):
1325        #    wfaction = 'return'
1326        #    try:
1327        #        self.portal_workflow.doActionFor(student_obj,wfaction)
1328        #        logger.info('%s, wf state changed' % sid)
1329        #        any_change = True
1330        #    except:
1331        #        logger.info('%s, wf transition failed, old state = %s' % (sid,res[0].review_state))
1332        #        pass
1333        ## end inclusion
1334
1335
1336        if any_change:
1337            return sid,''
1338        else:
1339            return sid,'not modified'
1340    ###)
1341
1342    security.declareProtected(ModifyPortalContent,"importData")###(
1343    def importData(self,filename,name,edit=False,bypass_queue_catalog=False):
1344        """load data from CSV values"""
1345        import transaction
1346        import random
1347
1348        pm = self.portal_membership
1349        member = pm.getAuthenticatedMember()
1350
1351        logger = logging.getLogger('WAeUPTool.importData')
1352        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1353        students_folder = self.portal_url.getPortalObject().campus.students
1354        start = True
1355        tr_count = 1
1356        total_imported = 0
1357        total_not_imported = 0
1358        total = 0
1359        iname = "import_%s" % name
1360        stool = getToolByName(self, 'portal_schemas')
1361        ltool = getToolByName(self, 'portal_layouts')
1362        schema = stool._getOb(iname)
1363        if schema is None:
1364            em = 'No such schema %s' % iname
1365            logger.error('No such schema %s' % iname)
1366            return em
1367        layout = ltool._getOb(iname)
1368        if layout is None:
1369            em = 'No such layout %s' % iname
1370            logger.error(em)
1371            return em
1372        validators = {}
1373        for widget in layout.keys():
1374            validators[widget] = layout[widget].validate
1375        #import pdb;pdb.set_trace()
1376        mode = "create"
1377        if edit:
1378            mode = "edit"
1379        importer_name = "mass_%(mode)s_%(name)s" % vars()
1380        importer = getattr(self, '%s' % importer_name,None)
1381        if importer is None:
1382            em = 'No importer function %s' % importer_name
1383            logger.error(em)
1384            return em
1385        not_imported = []
1386        imported = []
1387        try:
1388            items = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
1389        except:
1390            em = 'Error reading %s.csv' % filename
1391            logger.error(em)
1392            return em
1393        for item in items:
1394            if start:
1395                start = False
1396                adapters = [MappingStorageAdapter(schema, item)]
1397                logger.info('%s starts import from %s.csv in %s mode with schema and layout %s' % (member,filename,mode,iname))
1398                attrs = csv.reader(open("%s/import/%s.csv" % (i_home,filename),"rb")).next()
1399                import_keys = [k for k in attrs if not k.startswith('ignore')]
1400                diff2schema = set(import_keys).difference(set(schema.keys()))
1401                diff2layout = set(import_keys).difference(set(layout.keys()))
1402                if diff2schema:
1403                    em = 'not ignorable key(s): "%s" found in heading' % ", ".join(diff2schema)
1404                    return em
1405                s = ','.join(['"%s"' % fn for fn in import_keys])
1406                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(s + ',"Error"'+ '\n')
1407                s = '"id",' + s
1408                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
1409                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
1410                format_error = format + ',"%(Error)s"'
1411                format = '"%(id)s",'+ format
1412
1413            dm = DataModel(item, adapters,context=self)
1414            ds = DataStructure(data=item,datamodel=dm)
1415            error_string = ""
1416            for k in import_keys:
1417                #import pdb;pdb.set_trace()
1418                if not validators[k](ds,mode=mode):
1419                    error_string += " %s : %s" % (k,
1420                                                  self.translation_service(ds.getError(k),
1421                                                                           ds.getErrorMapping(k)))
1422            if not error_string:
1423                item.update(dm)
1424                item['id'],error = importer(item)
1425                if error:
1426                    error_string += error
1427            if error_string:
1428                item['Error'] = error_string
1429                not_imported.append(format_error % item)
1430                total_not_imported += 1
1431            else:
1432                em = format % item
1433                imported.append(em)
1434                logger.info("%(total_imported)d of %(total)d %(em)s" % vars())
1435                tr_count += 1
1436                total_imported += 1
1437            total += 1
1438            if total and not total % 100:
1439                transaction.commit()
1440                if len(not_imported) > 0:
1441                    open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1442                             '\n'.join(not_imported) + '\n')
1443                    not_imported = []
1444                if len(imported) > 0:
1445                    open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
1446                             '\n'.join(imported) + '\n')
1447                    imported = []
1448                em = '%d transactions committed\n' % (tr_count)
1449                regs = []
1450                logger.info(em)
1451                tr_count = 0
1452        if len(imported) > 0:
1453            open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
1454                                                '\n'.join(imported))
1455        if len(not_imported) > 0:
1456            open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1457                                                '\n'.join(not_imported))
1458        em = "Imported: %d, not imported: %d of total %d" % (total_imported,total_not_imported,total)
1459        return em
1460    ###)
1461
1462    security.declareProtected(ModifyPortalContent,"moveImagesToFS")###(
1463    def moveImagesToFS(self,student_id="O738726"):
1464        "move the images to the filesystem"
1465        images_dir = os.path.join("%s/images" % i_home,student_id)
1466        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1467        stool = getToolByName(self, 'portal_schemas')
1468        schemas = ['student_application',
1469                   'student_clearance',
1470                   ]
1471        created = False
1472        for schema_id in schemas:
1473            schema = stool._getOb(schema_id)
1474            object = getattr(student_folder,schema_id[len('student_'):],None)
1475            if object is None:
1476                continue
1477            doc = object.getContent()
1478            for key in schema.keys():
1479                if schema[key].meta_type != "CPS Image Field":
1480                    continue
1481                #import pdb;pdb.set_trace()
1482                image = getattr(doc,key)
1483                if not hasattr(image,"data"):
1484                    continue
1485                if not created:
1486                    if not os.path.exists(images_dir):
1487                        os.mkdir(images_dir)
1488                    created = True
1489                filename = os.path.join(images_dir,"%(key)s_%(student_id)s.jpg" % vars())
1490                open(filename,"wb").write(str(image.data))
1491
1492    security.declareProtected(ModifyPortalContent,"movePassportToFS")###(
1493    def movePassportToFS(self,student_id="O738726"):
1494        "move the passports to the filesystem"
1495        images_dir = os.path.join("%s" % i_home,'passports')
1496        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1497        stool = getToolByName(self, 'portal_schemas')
1498        schemas = ['student_application',
1499                   #'student_clearance',
1500                   ]
1501        created = False
1502        for schema_id in schemas:
1503            schema = stool._getOb(schema_id)
1504            object = getattr(student_folder,schema_id[len('student_'):],None)
1505            if object is None:
1506                continue
1507            doc = object.getContent()
1508            for key in schema.keys():
1509                if schema[key].meta_type != "CPS Image Field":
1510                    continue
1511                #import pdb;pdb.set_trace()
1512                image = getattr(doc,key)
1513                if not hasattr(image,"data"):
1514                    continue
1515                if not created:
1516                    if not os.path.exists(images_dir):
1517                        os.mkdir(images_dir)
1518                    created = True
1519                filename = os.path.join(images_dir,"%(student_id)s.jpg" % vars())
1520                open(filename,"wb").write(str(image.data))
1521
1522InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.