source: WAeUP_SRP/base/WAeUPTool.py @ 2339

Last change on this file since 2339 was 2335, checked in by joachim, 17 years ago

use File Image Widget in clearance, don't use on live system

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