source: WAeUP_SRP/base/WAeUPTool.py @ 2281

Last change on this file since 2281 was 2268, checked in by Henrik Bettermann, 18 years ago

allow overwriting of matric_no or jamb_reg_no if student id is provided

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