source: WAeUP_SRP/trunk/WAeUPTool.py @ 1757

Last change on this file since 1757 was 1756, checked in by joachim, 18 years ago

New form import
added portal status message to main_template

  • Property svn:keywords set to Id
File size: 34.3 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 1756 2007-05-08 15:01:11Z 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
29
30from Products.CPSSchemas.DataStructure import DataStructure
31from Products.CPSSchemas.DataModel import DataModel
32from Products.CPSSchemas.StorageAdapter import MappingStorageAdapter
33from Products.CMFCore.ActionProviderBase import ActionProviderBase
34from Products.CMFCore.permissions import View
35from Products.ZCatalog.ZCatalog import ZCatalog
36from Products.CMFCore.permissions import ModifyPortalContent
37from Products.CMFCore.utils import UniqueObject
38from Products.CMFCore.URLTool import URLTool
39from Products.CMFCore.utils import getToolByName
40from Students import makeCertificateCode
41from Globals import package_home,INSTANCE_HOME
42p_home = package_home(globals())
43i_home = INSTANCE_HOME
44import DateTime
45import logging
46import transaction
47import csv,re,os
48from Products.AdvancedQuery import Eq, Between, Le,In
49
50def getObject(object,name):
51    if object.hasObject(name):
52        return getattr(object,name)
53    return None
54
55class WAeUPTool(UniqueObject, SimpleItem, ActionProviderBase):
56    """WAeUP tool"""
57
58    id = 'waeup_tool'
59    meta_type = 'WAeUP Tool'
60    _actions = ()
61
62    security = ClassSecurityInfo()
63    security.declareObjectProtected(View)
64
65    manage_options = ( ActionProviderBase.manage_options
66                     + SimpleItem.manage_options
67                     )
68
69    def rwrite(self,s):
70        response = self.REQUEST.RESPONSE
71        response.setHeader('Content-type','text/html; charset=ISO-8859-15')
72        response.write("%s<br />\r\n" % s)
73
74    security.declareProtected(ModifyPortalContent,'openLog')
75    def openLog(self,name):
76        """open a log file"""
77        version = 1
78        path = "%s/log/%s_%d.log" % (i_home,name,version)
79        while os.path.exists(path):
80            version += 1
81            path = "%s/log/%s_%d.log" % (i_home,name,version)
82        log = open(path,"w")
83        return log
84
85    security.declareProtected(ModifyPortalContent,'writeLog')
86    def writeLog(self,logfile,s):
87        """write to the log file"""
88        logfile.write(s)
89
90
91    def generateStudentId(self,letter): ###(
92        import random
93        r = random
94        ##if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
95        if letter == '?':
96            letter= r.choice('ABCDEFGHKLMNPQRSTUVWXY')
97        sid = "%c%d" % (letter,r.randint(99999,1000000))
98        students = self.portal_url.getPortalObject().campus.students
99##        while hasattr(students, sid):
100##            sid = "%c%d" % (letter,r.randint(99999,1000000))
101        while self.students_catalog(id = sid):
102            sid = "%c%d" % (letter,r.randint(99999,1000000))
103        return sid
104    ###)
105
106    def generatePassword(self,s=None): ###(
107        import random
108        r = random
109        ##if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
110        if s is None:
111            s = 'abcdefghklmnpqrstuvwxy23456789'
112        pw = ''
113        while len(pw) < 6:
114            pw += r.choice(s)
115        return pw
116    ###)
117
118    security.declareProtected(ModifyPortalContent,'getCredential') ###(
119    def getCredential(self,student_id):
120        "return a student password"
121        student_entry = getattr(self.portal_directories.students,student_id,None)
122        if student_entry is None:
123            return None
124        return getattr(student_entry,"password","not set")
125    ###)
126
127    security.declarePublic('checkPassword') ###(
128    def checkPassword(self,student_id,password):
129        "return a student password"
130        student_entry = getattr(self.portal_directories.students,student_id,None)
131        if student_entry is None:
132            return False
133        return getattr(student_entry,"password","not set") == password
134    ###)
135
136    security.declarePublic('editPassword') ###(
137    def editPassword(self,student_id,password):
138        "edit a student password"
139        student_entry = getattr(self.portal_directories.students,student_id,None)
140        if student_entry is None:
141            return
142        setattr(student_entry,'password',password)
143    ###)
144
145    security.declareProtected(View,'doCommit') ###(
146    def doCommit(self,logger=None):
147        "commit some transactions"
148        transaction.commit()
149    ###)
150
151    security.declarePublic('loadStudentFoto') ###(
152    def loadStudentFoto(self,student):
153        "return a student passport picture"
154        app_doc = student.application.getContent()
155        clear = student.clearance
156        clear_doc = clear.getContent()
157        matric_no = clear_doc.matric_no.upper()
158        picture1 ="%s/import/pictures_returning/%s.jpg" % (i_home,matric_no)
159        picture2 ="%s/import/pictures_returning/%s.JPG" % (i_home,matric_no)
160        #import pdb;pdb.set_trace()
161        if os.path.exists(picture1):
162            file = open(picture1)
163        elif os.path.exists(picture2):
164            file = open(picture2)
165        else:
166            return "passport picture not found %s" % picture1
167
168        outfile = file.read()
169        app_doc.manage_addFile('passport',
170                               file=outfile,
171                               title="%s.jpg" % matric_no)
172        return "successfully loaded passport picture"
173    ###)
174
175    security.declareProtected(ModifyPortalContent,'createOne') ###(
176    def createOne(self,students_folder,student_brain,letter,commit=False):
177        sid = self.waeup_tool.generateStudentId(letter)
178        students_folder.invokeFactory('Student', sid)
179        student = getattr(students_folder,sid)
180        self.portal_workflow.doActionFor(student,'return')
181        student.manage_setLocalRoles(sid, ['Owner',])
182        matric_no = student_brain.matric_no
183        jamb_reg_no = student_brain.Entryregno
184        self.students_catalog.addRecord(id = sid,
185                                           matric_no = matric_no,
186                                           jamb_reg_no = jamb_reg_no,
187                                           sex = student_brain.Sex == "F",
188                                           name = "%s %s %s" % (student_brain.Firstname,
189                                                                student_brain.Middlename,
190                                                                student_brain.Lastname)
191                                        )
192        if commit:
193            transaction.commit()
194        return sid,jamb_reg_no
195    ###)
196
197    security.declareProtected(ModifyPortalContent,'addStudent') ###(
198    def addStudent(self,dict):
199        students_folder = self.portal_url.getPortalObject().campus.students
200        sid = self.waeup_tool.generateStudentId('?')
201        students_folder.invokeFactory('Student', sid)
202        student_obj = getattr(students_folder,sid)
203        password = self.generatePassword()
204        self.makeStudentMember(sid,password)
205        f2t = self.student_field2types
206        for pt in f2t.keys():
207            student_obj.invokeFactory(pt,f2t[pt]['id'])
208            sub_obj = getattr(student_obj,f2t[pt]['id'])
209            sub_doc = sub_obj.getContent()
210            self.portal_workflow.doActionFor(sub_obj,'open',dest_container=sub_obj)
211            d = {'Title': f2t[pt]['title']}
212            for field in f2t[pt]['fields']:
213                d[field] = dict.get(field,'')
214            if pt == 'StudentPersonal':
215                d['sex'] = dict.get('sex') == 'F'
216            sub_doc.edit(mapping = d)
217            self.portal_workflow.doActionFor(sub_obj,'close',dest_container=sub_obj)
218
219        entry_session = dict.get('entry_session')
220        wfaction = 'return'
221        if entry_session == self.getSessionId():
222            wfaction = 'admit'
223        self.portal_workflow.doActionFor(student_obj,wfaction)
224        student_obj.manage_setLocalRoles(sid, ['Owner',])
225        return sid,password
226    ###)
227
228    security.declarePublic('getCertificateBrain') ###(
229    def getCertificateBrain(self,cert_id):
230        "do it"
231        res = ZCatalog.searchResults(self.portal_catalog,
232                                {'portal_type':"Certificate",
233                                      'id': cert_id})
234        if res:
235            return res[0]
236        return None
237    ###)
238
239    security.declareProtected(ModifyPortalContent,'get_csv_filenames') ###(
240    def get_csv_filenames(self):
241        "do it"
242        files = [file for file in os.listdir("%s/import/" % (i_home))
243                 if file.endswith('.csv') and file.find('imported') == -1]
244        return files
245    ###)
246
247    security.declarePublic('findStudentByMatricelNo') ###(
248    def findStudentByMatricelNo(self,matric_no):
249        "do it"
250        res = ZCatalog.searchResults(self.portal_catalog,
251                                {'portal_type':"StudentClearance",
252                                 'SearchableText': matric_no})
253        if res:
254            return res[0]
255        return None
256    ###)
257
258    security.declarePublic('makeStudentMember') ###(
259    def makeStudentMember(self,sid,password='uNsEt'):
260        """make the student a member"""
261        membership = self.portal_membership
262        membership.addMember(sid,
263                             password ,
264                             roles=('Member',
265                                     'Student',
266                                     ),
267                             domains='',
268                             properties = {'memberareaCreationFlag': False,
269                                           'homeless': True},)
270        member = membership.getMemberById(sid)
271        self.portal_registration.afterAdd(member, sid, password, None)
272        #self.manage_setLocalRoles(sid, ['Owner',])
273    ###)
274
275    security.declarePublic('makeStudentData') ###(
276    def makeStudentData(self,student_id,email=None,phone_nr=None):
277        "create Datastructure for a returning Student"
278        #import pdb;pdb.set_trace()
279        logger = logging.getLogger('WAeUPTool.makeStudentData')
280        students_folder = self.portal_url.getPortalObject().campus.students
281        res = self.students_catalog(id=student_id)
282        if res:
283            st = res[0]
284        res = self.returning_import(matric_no = st.matric_no)
285        if res:
286            student = res[0]
287        logger.info('%s creates data structure' % student_id)
288        s_results = self.results_import(matric_no = st.matric_no)
289        lnr = self.getLevelFromResultsCosCode(s_results)
290        level = "%d00" % lnr
291        verdict,eligible = self.getVerdict(s_results[0].Verdict)
292        if eligible:
293            level = "%d00" % (lnr + 1)
294##        level = s_results[0].Level
295##        for result in s_results:
296##            if level != result.Level:
297##                logger.info('"%s", "Levels differ","%s != %s"' % (student_id,level,result.Level))
298        #student should not be allowed to perform this transition
299        #wftool = self.portal_workflow
300        #wftool.doActionFor(student,'return')
301        certcode_org = student.Coursemajorcode
302        certcode = makeCertificateCode(certcode_org)
303        certificate_brain = self.getCertificateBrain(certcode)
304        if not certificate_brain:
305            em = 'Certificate %s org-code %s not found\n' % (certcode, certcode_org)
306            logger.info(em)
307        matric_no = student.matric_no
308        sid = student_id
309        student_obj = getattr(students_folder,sid)
310        student_obj.invokeFactory('StudentApplication','application')
311        application = student_obj.application
312        self.portal_workflow.doActionFor(application,'open',dest_container=application)
313        da = {'Title': 'Application Data'}
314        student_obj.invokeFactory('StudentPersonal','personal')
315        da['jamb_reg_no'] = student.Entryregno
316        em = self.getEntryMode(student.Entryregno)
317##        em = student.Mode_of_Entry
318##        if em in ('DIRECT', 'DIRECT ENTRY',):
319##            em = 'DE'
320##        elif em in ('U.M.E', 'UNE',):
321##            em = 'UME'
322##        elif not em:
323##            em = "unknown"
324        da['entry_mode'] = em
325        personal = student_obj.personal
326        self.portal_workflow.doActionFor(personal,'open',dest_container=personal)
327        dp = {'Title': 'Personal Data'}
328        student_obj.invokeFactory('StudentClearance','clearance')
329        clearance = student_obj.clearance
330        self.portal_workflow.doActionFor(clearance,'open',dest_container=clearance)
331        dc = {'Title': 'Clearance/Eligibility Record'}
332        dc['matric_no'] = matric_no
333        state = student.State
334        lga = student.LGA
335        if state and lga:
336            lga =  state + ' / ' + lga
337        else:
338            lga = "None"
339        da['jamb_lga'] = dc['lga'] = lga
340        da['app_email'] = dp['email'] = email
341        da['app_mobile'] = dp['phone'] = phone_nr
342        dp['firstname'] = student.Firstname
343        dp['middlename'] = student.Middlename
344        dp['lastname'] = student.Lastname
345        da['jamb_lastname'] = "%s %s %s" % (student.Firstname,student.Middlename,student.Lastname)
346        da['jamb_sex'] = student.Sex
347        dp['sex'] = student.Sex == 'F'
348        dp['perm_address'] = student.Permanent_Address
349        application.getContent().edit(mapping=da)
350        self.portal_workflow.doActionFor(application,'close',dest_container=application)
351        personal.getContent().edit(mapping=dp)
352        clearance.getContent().edit(mapping=dc)
353        self.portal_workflow.doActionFor(clearance,'close',dest_container=clearance)
354        catd = {}
355        catd['id'] = sid
356        catd['entry_mode']= da['entry_mode']
357        catd['matric_no'] = matric_no
358        catd['jamb_reg_no'] = da['jamb_reg_no']
359        catd['name'] = "%(firstname)s %(middlename)s %(lastname)s" % dp
360        catd['sex'] = dp['sex']
361        catd['level'] = level
362        catd['verdict'] = verdict
363        if certificate_brain:
364            cpath = certificate_brain.getPath().split('/')
365            catd['faculty'] = cpath[-4]
366            catd['department'] = cpath[-3]
367            catd['course'] = certcode
368        self.students_catalog.modifyRecord(**catd)
369        #
370        # Study Course
371        #
372        student_obj.invokeFactory('StudentStudyCourse','study_course')
373        studycourse = student_obj.study_course
374        self.portal_workflow.doActionFor(studycourse,'open',dest_container=studycourse)
375        dsc = {}
376        dsc['study_course'] = certcode
377        dsc['current_level'] = level
378        dsc['current_verdict'] = verdict
379        studycourse.getContent().edit(mapping=dsc)
380        #
381        # Level
382        #
383##        l = getattr(studycourse,level,None)
384##        if l is None:
385##            studycourse.invokeFactory('StudentStudyLevel', level)
386##            l = getattr(studycourse, level)
387##            self.portal_workflow.doActionFor(l,'open',dest_container=l)
388##            l.getContent().edit(mapping={'Title': "Level %s" % level})
389###)
390
391    security.declarePublic('makeStudentLevel') ###(
392    def makeStudentLevel(self,student_id):
393        "create the StudyLevel for a returning Student"
394        #import pdb;pdb.set_trace()
395        logger = logging.getLogger('WAeUPTool.makeStudentLevel')
396        students_folder = self.portal_url.getPortalObject().campus.students
397        res = self.students_catalog(id=student_id)
398        if res:
399            st = res[0]
400        course = st.course
401        matric_no = st.matric_no
402        level = st.level
403        res = self.results_import(matric_no = matric_no)
404        if res:
405            results = res
406        logger.info('%s creating Level %s' % (student_id,level))
407        #
408        # Level
409        #
410        student_obj = getattr(self.portal_url.getPortalObject().campus.students,student_id)
411        studycourse = getattr(student_obj,"study_course",None)
412        self.portal_workflow.doActionFor(studycourse,'close_for_edit',dest_container=studycourse)
413        l = getattr(studycourse,level,None)
414        if l is None:
415            studycourse.invokeFactory('StudentStudyLevel', level)
416            l = getattr(studycourse, level)
417            self.portal_workflow.doActionFor(l,'open',dest_container=l)
418            l.getContent().edit(mapping={'Title': "Level %s" % level})
419        ###)
420
421    security.declarePublic('getAccommodationInfo') ###(
422    def getAccommodationInfo(self,bed):
423        """return Accommodation Info"""
424        info = {}
425        hall,block,room,letter = bed.split('_')
426        res = ZCatalog.searchResults(self.portal_catalog,portal_type="AccoHall",id=hall)
427        if res and len(res) == 1:
428            hall_brain = res[0]
429            hall_doc = hall_brain.getObject().getContent()
430        else:
431            return info
432        info['hall_title'] = hall_brain.Title
433        info['maintenance_code'] = hall_doc.maintenance_code
434        res = ZCatalog.searchResults(self.portal_catalog,portal_type="ScratchCardBatch")
435        batch_doc = None
436        for brain in res:
437            if brain.id.startswith(info['maintenance_code']):
438                batch_doc = brain.getObject().getContent()
439                break
440        if batch_doc is None:
441            info['maintenance_fee'] = None
442        else:
443            info['maintenance_fee'] = batch_doc.cost
444        return info
445    ###)
446
447    security.declareProtected(ModifyPortalContent,'deleteAllCourses') ###(
448    def deleteAllCourses(self,department="All"):
449        ''' delete the courses'''
450        pm = self.portal_membership
451        member = pm.getAuthenticatedMember()
452
453        if str(member) not in ("henrik","joachim"):
454            return "not possible"
455        if department == "All":
456            res = self.portal_catalog({'meta_type': 'Department'})
457        if len(res) < 1:
458            return "No Departments found"
459
460        deleted = []
461        for dep in res:
462            cf = dep.getObject().courses
463            if cf:
464                cf.manage_delObjects(ids=cf.objectIds())
465                deleted.append("deleted Courses in %s" % dep.getId)
466        return "\r".join(deleted)
467    ###)
468
469    security.declareProtected(ModifyPortalContent,'getLogfileLines') ###(
470    def getLogfileLines(self,filename="event.log",numlines=20):
471        """Get last NUMLINES lines of logfile FILENAME.
472
473        Return last lines' of a file in the instances logfile directory as
474        a list. The number of returned lines equals `numlines' or less. If
475        less than `numlines' lines are available, the whole file ist
476        returned. If the file can not be opened or some other error
477        occurs, empty list is returend.
478        """
479        result = []
480        lines_hit = 0
481
482        # We only handle files in instances' log directory...
483        logpath = os.path.join(i_home, "log")
484        filename = str(os.path.abspath( os.path.join( logpath, filename )))
485        if not filename.startswith( logpath ):
486            # Attempt to access file outside log-dir...
487            return []
488
489        try:
490            fd = file( filename, "rb" )
491        except IOError:
492            return []
493        if not fd:
494            return []
495
496        if os.linesep == None:
497            linesep = '\n'
498        else:
499            linesep = os.linesep
500
501        # Try to find 'numlines' times a lineseparator, searching from end
502        # and moving to the beginning of file...
503        fd.seek( 0, 2) # Move to end of file...
504        while lines_hit < numlines:
505            if fd.read(1) == linesep[-1]: # This moves filedescriptor
506                                          # one step forward...
507                lines_hit += 1
508            try:
509                fd.seek( -2, 1) # Go two bytes back from current pos...
510            except IOError:
511                # We cannot go back two bytes. Maybe the file is too small...
512                break
513        fd.seek(2,1)
514
515        # Read all lines from current position...
516        result = fd.readlines()
517        # Remove line endings...
518        result = [x.strip() for x in result]
519        fd.close()
520        return result
521    ###)
522
523    security.declareProtected(ModifyPortalContent,"getCallbacksFromLog")###(
524    def getCallbacksFromLog(self,filename):
525        """fix Online Payment Transactions from Z2.log entries"""
526        import transaction
527        import random
528        from cgi import parse_qs
529        from urlparse import urlparse
530        #from pdb import set_trace
531        wftool = self.portal_workflow
532        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
533        students_folder = self.portal_url.getPortalObject().campus.students
534        s = r'(?P<client_ip>\S+) - (?P<member_id>\S+) \['
535        s += r'(?P<date>.*)\] "(?P<get>.*)" (?P<codes>\d+ \d+) "'
536        s += r'(?P<intersw>.*)" "(?P<agent>.*)"'
537        data = re.compile(s)
538        start = True
539        tr_count = 1
540        total = 0
541        #name = 'pume_results'
542        #name = 'epaymentsuccessful_z2log2'
543        name = filename
544        no_import = []
545        imported = []
546        logger = logging.getLogger('WAeUPTool.getFailedTransactions')
547        try:
548            transactions = open("%s/import/%s" % (i_home,name),"rb").readlines()
549        except:
550            logger.error('Error reading %s' % name)
551            return
552        tas = []
553        for line in transactions:
554            dict = {}
555            items = data.search(line)
556            dict['idict'] = idict = items.groupdict()
557            #print idict
558            #from pdb import set_trace;set_trace()
559            urlparsed = urlparse(idict['get'][4:])
560            #print urlparsed
561            path = urlparsed[2].split('/')
562            dict['student_id'] = student_id = path[8]
563            dict['payment_id'] = payment_id = path[10]
564            dict['qs_dict'] = qs_dict = parse_qs(urlparsed[4])
565            tas.append(dict)
566            tr_count += 1
567        return tas
568    ###)
569
570    security.declareProtected(ModifyPortalContent,"importOnlinePaymentTransactions")###(
571    def importOnlinePaymentTransactions(self):
572        """load Online Payment Transactions from CSV values"""
573        import transaction
574        import random
575        #from pdb import set_trace
576        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
577        opt = self.online_payments_import
578        students_folder = self.portal_url.getPortalObject().campus.students
579        start = True
580        tr_count = 1
581        total = 0
582        #name = 'pume_results'
583        name = 'OnlineTransactions'
584        no_import = []
585        imported = []
586        logger = logging.getLogger('WAeUPTool.importOnlinePaymentTransactions')
587        try:
588            transactions = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
589        except:
590            logger.error('Error reading %s.csv' % name)
591            return
592        for pay_transaction in transactions:
593            if start:
594                start = False
595                logger.info('Start loading from %s.csv' % name)
596                s = ','.join(['"%s"' % fn for fn in pay_transaction.keys()])
597                no_import.append('%s,"Error"' % s)
598                format = ','.join(['"%%(%s)s"' % fn for fn in pay_transaction.keys()])
599                format_error = format + ',"%(Error)s"'
600            data = {}
601
602            # format of the first file sent from Tayo
603            #data['datetime'] = date = DateTime.DateTime(pay_transaction['Date'])
604            #data['student_id'] = student_id = pay_transaction['Payer ID']
605            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
606            #data['response_code'] = response_code = pay_transaction['Resp Code']
607            #data['amount'] = amount = pay_transaction['Amount']
608
609            # format of the second file sent from Tayo
610            data['datetime'] = date = 0
611            data['student_id'] = student_id = pay_transaction['Payer ID']
612            data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
613            data['response_code'] = response_code = '00'
614            data['amount'] = amount = pay_transaction['Amount']
615
616            dup = False
617            if response_code == "12":
618                continue
619            try:
620                opt.addRecord(**data)
621            except ValueError:
622                dup = True
623            #from pdb import set_trace;set_trace()
624            if dup:
625                if response_code == "00":
626                    opt.modifyRecord(**data)
627                else:
628                    pay_transaction['Error'] = "Duplicate order_id"
629                    no_import.append( format_error % pay_transaction)
630                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
631                    continue
632            tr_count += 1
633            if tr_count > 1000:
634                if len(no_import) > 0:
635                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
636                             '\n'.join(no_import) + '\n')
637                    no_import = []
638                em = '%d transactions committed\n' % (tr_count)
639                transaction.commit()
640                regs = []
641                logger.info(em)
642                total += tr_count
643                tr_count = 0
644        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
645                                                '\n'.join(no_import))
646        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
647    ###)
648
649    student_field2types = {   ###(
650                      'StudentApplication':
651                          {'id': 'application',
652                           'title': 'Application Data',
653                           'wf_state': 'close',
654                           'fields':
655                             ('jamb_reg_no',
656                              'entry_mode',
657                              #'entry_level',
658                              'entry_session',
659                              'jamb_score',
660                              'email',
661                              'phone',
662                              )
663                              },
664                      'StudentPume':
665                          {'id': 'pume',
666                           'title': 'Pume Data',
667                           'wf_state': 'close',
668                           'fields':
669                             ('pume_score',
670                              )
671                              },
672                      'StudentClearance':
673                          {'id': 'clearance',
674                           'title': 'Clearance Data',
675                           'wf_state': 'close',
676                           'fields':
677                             ('matric_no',
678                              'nationality',
679                              'lga',
680                              )
681                              },
682                         'StudentPersonal':
683                          {'id': 'personal',
684                           'title': 'Personal Data',
685                           'wf_state': 'close',
686                           'fields':
687                             ('firstname',
688                              'middlename',
689                              'lastname',
690                              'sex',
691                              'email',
692                              'phone',
693                              'perm_address',
694                              )
695                              },
696                         'StudentStudyCourse':
697                          {'id': 'study_course',
698                           'title': 'Study Course',
699                           'wf_state': 'close',
700                           'fields':
701                             ('study_course',
702                              'current_level',
703                              'current_session',
704                              'current_mode',
705                              'current_verdict',
706                              )
707                              },
708                         }
709    ###)
710
711
712    security.declareProtected(ModifyPortalContent,'import_student') ###(
713    def import_student(self,dict):
714        "create a students data"
715        logger = logging.getLogger('WAeUPTool.create_student')
716        students_folder = self.portal_url.getPortalObject().campus.students
717        jamb_reg_no = dict.get('jamb_reg_no',None)
718        if jamb_reg_no:
719            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
720            if res:
721                return '',"jamb_reg_no exists"
722        matric_no = dict.get('matric_no',None)
723        if matric_no:
724            res = self.students_catalog(matric_no = matric_no)
725            if res:
726                return '',"matric_no exists"
727        sid = self.waeup_tool.generateStudentId('?')
728        students_folder.invokeFactory('Student', sid)
729        student_obj = getattr(students_folder,sid)
730        f2t = self.student_field2types
731        for pt in f2t.keys():
732            student_obj.invokeFactory(pt,f2t[pt]['id'])
733            sub_obj = getattr(student_obj,f2t[pt]['id'])
734            sub_doc = sub_obj.getContent()
735            self.portal_workflow.doActionFor(sub_obj,'open',dest_container=sub_obj)
736            d = {'Title': f2t[pt]['title']}
737            for field in f2t[pt]['fields']:
738                d[field] = dict.get(field,'')
739            if pt == 'StudentPersonal':
740                d['sex'] = dict.get('sex') == 'F'
741            sub_doc.edit(mapping = d)
742            self.portal_workflow.doActionFor(sub_obj,f2t[pt]['wf_state'],dest_container=sub_obj)
743        wfaction = 'return'
744        self.portal_workflow.doActionFor(student_obj,wfaction)
745        student_obj.manage_setLocalRoles(sid, ['Owner',])
746        return sid,''
747    ###)
748
749    security.declareProtected(ModifyPortalContent,"importData")###(
750    def importData(self,filename,name):
751        """load data from CSV values"""
752        import transaction
753        import random
754        logger = logging.getLogger('WAeUPTool.importData')
755        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
756        students_folder = self.portal_url.getPortalObject().campus.students
757        start = True
758        tr_count = 1
759        total_imported = 0
760        total_not_imported = 0
761        total = 0
762        iname = "import_%s" % name
763        stool = getToolByName(self, 'portal_schemas')
764        ltool = getToolByName(self, 'portal_layouts')
765        schema = stool._getOb(iname)
766        if schema is None:
767            em = 'No such schema import_%s' % iname
768            logger.error('No such schema import_%s' % iname)
769            return em
770        layout = ltool._getOb(iname)
771        if layout is None:
772            em = 'No such layout import_%s' % iname
773            logger.error(em)
774            return em
775        validators = {}
776        for widget in layout.keys():
777            validators[widget] = layout[widget].validate
778        creator = getattr(self, 'import_%s' % name,None)
779        if creator is None:
780            em = 'No creator function create_%s' % name
781            logger.error(em)
782            return em
783        not_imported = []
784        imported = []
785        try:
786            items = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
787        except:
788            em = 'Error reading %s.csv' % filename
789            logger.error(em)
790            return em
791        for item in items:
792            tr_count += 1
793            if start:
794                start = False
795                adapters = [MappingStorageAdapter(schema, item)]
796                dm = DataModel(item, adapters,context=self)
797                logger.info('Start importing from %s.csv' % filename)
798                import_keys = item.keys()
799                diff_set = set(import_keys).difference(set(schema.keys()))
800                if diff_set:
801                    logger.error('%s not in schema.' % diff_set)
802                    return
803                diff_set = set(import_keys).difference(set(layout.keys()))
804                if diff_set:
805                    logger.error('%s not in layout.' % diff_set)
806                    return
807                s = ','.join(['"%s"' % fn for fn in import_keys])
808                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
809                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write('%s,"Error"' %s + '\n')
810                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
811                format_error = format + ',"%(Error)s"'
812                #from pdb import set_trace; set_trace()
813                format = '"%(id)s",'+ format
814            ds = DataStructure(data=item,datamodel=dm)
815            error_string = ""
816            for k in import_keys:
817                if not validators[k](ds):
818                    error_string += " %s : %s" % (k,ds.getError(k))
819            if not error_string:
820                item.update(dm)
821                item['id'],error = creator(item)
822                if error:
823                    error_string += error
824            if error_string:
825                item['Error'] = error_string
826                not_imported.append(format_error % item)
827                total_not_imported += 1
828            else:
829                imported.append(format % item)
830                total_imported += 1
831            total += 1
832            if tr_count > 1000:
833                if len(not_imported) > 0:
834                    open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
835                             '\n'.join(not_imported) + '\n')
836                    not_imported = []
837                if len(imported) > 0:
838                    open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
839                             '\n'.join(not_imported) + '\n')
840                    imported = []
841                em = '%d transactions committed\n' % (tr_count)
842                transaction.commit()
843                regs = []
844                logger.info(em)
845                tr_count = 0
846        if len(imported) > 0:
847            open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
848                                                '\n'.join(imported))
849        if len(not_imported) > 0:
850            open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
851                                                '\n'.join(not_imported))
852        em = "Imported: %d, not imported: %d of total %d" % (total_imported,total_not_imported,total)
853        logger.info(em)
854        return em
855    ###)
856
857InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.