source: WAeUP_SRP/trunk/WAeUPTool.py @ 1767

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

makeStudentData must not change catalog
makeStudentData must set current_session

  • Property svn:keywords set to Id
File size: 34.4 KB
Line 
1#-*- mode: python; mode: fold -*-
2# (C) Copyright 2005 The WAeUP group  <http://www.waeup.org>
3# Author: Joachim Schmitz (js@aixtraware.de)
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License version 2 as published
7# by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software
16# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17# 02111-1307, USA.
18#
19# $Id: WAeUPTool.py 1759 2007-05-08 21:43:38Z henrik $
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        dsc['current_session'] = '06'
380        studycourse.getContent().edit(mapping=dsc)
381        #
382        # Level
383        #
384##        l = getattr(studycourse,level,None)
385##        if l is None:
386##            studycourse.invokeFactory('StudentStudyLevel', level)
387##            l = getattr(studycourse, level)
388##            self.portal_workflow.doActionFor(l,'open',dest_container=l)
389##            l.getContent().edit(mapping={'Title': "Level %s" % level})
390###)
391
392    security.declarePublic('makeStudentLevel') ###(
393    def makeStudentLevel(self,student_id):
394        "create the StudyLevel for a returning Student"
395        #import pdb;pdb.set_trace()
396        logger = logging.getLogger('WAeUPTool.makeStudentLevel')
397        students_folder = self.portal_url.getPortalObject().campus.students
398        res = self.students_catalog(id=student_id)
399        if res:
400            st = res[0]
401        course = st.course
402        matric_no = st.matric_no
403        level = st.level
404        res = self.results_import(matric_no = matric_no)
405        if res:
406            results = res
407        logger.info('%s creating Level %s' % (student_id,level))
408        #
409        # Level
410        #
411        student_obj = getattr(self.portal_url.getPortalObject().campus.students,student_id)
412        studycourse = getattr(student_obj,"study_course",None)
413        self.portal_workflow.doActionFor(studycourse,'close_for_edit',dest_container=studycourse)
414        l = getattr(studycourse,level,None)
415        if l is None:
416            studycourse.invokeFactory('StudentStudyLevel', level)
417            l = getattr(studycourse, level)
418            self.portal_workflow.doActionFor(l,'open',dest_container=l)
419            l.getContent().edit(mapping={'Title': "Level %s" % level})
420        ###)
421
422    security.declarePublic('getAccommodationInfo') ###(
423    def getAccommodationInfo(self,bed):
424        """return Accommodation Info"""
425        info = {}
426        hall,block,room,letter = bed.split('_')
427        res = ZCatalog.searchResults(self.portal_catalog,portal_type="AccoHall",id=hall)
428        if res and len(res) == 1:
429            hall_brain = res[0]
430            hall_doc = hall_brain.getObject().getContent()
431        else:
432            return info
433        info['hall_title'] = hall_brain.Title
434        info['maintenance_code'] = hall_doc.maintenance_code
435        res = ZCatalog.searchResults(self.portal_catalog,portal_type="ScratchCardBatch")
436        batch_doc = None
437        for brain in res:
438            if brain.id.startswith(info['maintenance_code']):
439                batch_doc = brain.getObject().getContent()
440                break
441        if batch_doc is None:
442            info['maintenance_fee'] = None
443        else:
444            info['maintenance_fee'] = batch_doc.cost
445        return info
446    ###)
447
448    security.declareProtected(ModifyPortalContent,'deleteAllCourses') ###(
449    def deleteAllCourses(self,department="All"):
450        ''' delete the courses'''
451        pm = self.portal_membership
452        member = pm.getAuthenticatedMember()
453
454        if str(member) not in ("henrik","joachim"):
455            return "not possible"
456        if department == "All":
457            res = self.portal_catalog({'meta_type': 'Department'})
458        if len(res) < 1:
459            return "No Departments found"
460
461        deleted = []
462        for dep in res:
463            cf = dep.getObject().courses
464            if cf:
465                cf.manage_delObjects(ids=cf.objectIds())
466                deleted.append("deleted Courses in %s" % dep.getId)
467        return "\r".join(deleted)
468    ###)
469
470    security.declareProtected(ModifyPortalContent,'getLogfileLines') ###(
471    def getLogfileLines(self,filename="event.log",numlines=20):
472        """Get last NUMLINES lines of logfile FILENAME.
473
474        Return last lines' of a file in the instances logfile directory as
475        a list. The number of returned lines equals `numlines' or less. If
476        less than `numlines' lines are available, the whole file ist
477        returned. If the file can not be opened or some other error
478        occurs, empty list is returend.
479        """
480        result = []
481        lines_hit = 0
482
483        # We only handle files in instances' log directory...
484        logpath = os.path.join(i_home, "log")
485        filename = str(os.path.abspath( os.path.join( logpath, filename )))
486        if not filename.startswith( logpath ):
487            # Attempt to access file outside log-dir...
488            return []
489
490        try:
491            fd = file( filename, "rb" )
492        except IOError:
493            return []
494        if not fd:
495            return []
496
497        if os.linesep == None:
498            linesep = '\n'
499        else:
500            linesep = os.linesep
501
502        # Try to find 'numlines' times a lineseparator, searching from end
503        # and moving to the beginning of file...
504        fd.seek( 0, 2) # Move to end of file...
505        while lines_hit < numlines:
506            if fd.read(1) == linesep[-1]: # This moves filedescriptor
507                                          # one step forward...
508                lines_hit += 1
509            try:
510                fd.seek( -2, 1) # Go two bytes back from current pos...
511            except IOError:
512                # We cannot go back two bytes. Maybe the file is too small...
513                break
514        fd.seek(2,1)
515
516        # Read all lines from current position...
517        result = fd.readlines()
518        # Remove line endings...
519        result = [x.strip() for x in result]
520        fd.close()
521        return result
522    ###)
523
524    security.declareProtected(ModifyPortalContent,"getCallbacksFromLog")###(
525    def getCallbacksFromLog(self,filename):
526        """fix Online Payment Transactions from Z2.log entries"""
527        import transaction
528        import random
529        from cgi import parse_qs
530        from urlparse import urlparse
531        #from pdb import set_trace
532        wftool = self.portal_workflow
533        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
534        students_folder = self.portal_url.getPortalObject().campus.students
535        s = r'(?P<client_ip>\S+) - (?P<member_id>\S+) \['
536        s += r'(?P<date>.*)\] "(?P<get>.*)" (?P<codes>\d+ \d+) "'
537        s += r'(?P<intersw>.*)" "(?P<agent>.*)"'
538        data = re.compile(s)
539        start = True
540        tr_count = 1
541        total = 0
542        #name = 'pume_results'
543        #name = 'epaymentsuccessful_z2log2'
544        name = filename
545        no_import = []
546        imported = []
547        logger = logging.getLogger('WAeUPTool.getFailedTransactions')
548        try:
549            transactions = open("%s/import/%s" % (i_home,name),"rb").readlines()
550        except:
551            logger.error('Error reading %s' % name)
552            return
553        tas = []
554        for line in transactions:
555            dict = {}
556            items = data.search(line)
557            dict['idict'] = idict = items.groupdict()
558            #print idict
559            #from pdb import set_trace;set_trace()
560            urlparsed = urlparse(idict['get'][4:])
561            #print urlparsed
562            path = urlparsed[2].split('/')
563            dict['student_id'] = student_id = path[8]
564            dict['payment_id'] = payment_id = path[10]
565            dict['qs_dict'] = qs_dict = parse_qs(urlparsed[4])
566            tas.append(dict)
567            tr_count += 1
568        return tas
569    ###)
570
571    security.declareProtected(ModifyPortalContent,"importOnlinePaymentTransactions")###(
572    def importOnlinePaymentTransactions(self):
573        """load Online Payment Transactions from CSV values"""
574        import transaction
575        import random
576        #from pdb import set_trace
577        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
578        opt = self.online_payments_import
579        students_folder = self.portal_url.getPortalObject().campus.students
580        start = True
581        tr_count = 1
582        total = 0
583        #name = 'pume_results'
584        name = 'OnlineTransactions'
585        no_import = []
586        imported = []
587        logger = logging.getLogger('WAeUPTool.importOnlinePaymentTransactions')
588        try:
589            transactions = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
590        except:
591            logger.error('Error reading %s.csv' % name)
592            return
593        for pay_transaction in transactions:
594            if start:
595                start = False
596                logger.info('Start loading from %s.csv' % name)
597                s = ','.join(['"%s"' % fn for fn in pay_transaction.keys()])
598                no_import.append('%s,"Error"' % s)
599                format = ','.join(['"%%(%s)s"' % fn for fn in pay_transaction.keys()])
600                format_error = format + ',"%(Error)s"'
601            data = {}
602
603            # format of the first file sent from Tayo
604            #data['datetime'] = date = DateTime.DateTime(pay_transaction['Date'])
605            #data['student_id'] = student_id = pay_transaction['Payer ID']
606            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
607            #data['response_code'] = response_code = pay_transaction['Resp Code']
608            #data['amount'] = amount = pay_transaction['Amount']
609
610            # format of the second file sent from Tayo
611            data['datetime'] = date = 0
612            data['student_id'] = student_id = pay_transaction['Payer ID']
613            data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
614            data['response_code'] = response_code = '00'
615            data['amount'] = amount = pay_transaction['Amount']
616
617            dup = False
618            if response_code == "12":
619                continue
620            try:
621                opt.addRecord(**data)
622            except ValueError:
623                dup = True
624            #from pdb import set_trace;set_trace()
625            if dup:
626                if response_code == "00":
627                    opt.modifyRecord(**data)
628                else:
629                    pay_transaction['Error'] = "Duplicate order_id"
630                    no_import.append( format_error % pay_transaction)
631                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
632                    continue
633            tr_count += 1
634            if tr_count > 1000:
635                if len(no_import) > 0:
636                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
637                             '\n'.join(no_import) + '\n')
638                    no_import = []
639                em = '%d transactions committed\n' % (tr_count)
640                transaction.commit()
641                regs = []
642                logger.info(em)
643                total += tr_count
644                tr_count = 0
645        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
646                                                '\n'.join(no_import))
647        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
648    ###)
649
650    student_field2types = {   ###(
651                      'StudentApplication':
652                          {'id': 'application',
653                           'title': 'Application Data',
654                           'wf_state': 'close',
655                           'fields':
656                             ('jamb_reg_no',
657                              'entry_mode',
658                              #'entry_level',
659                              'entry_session',
660                              'jamb_score',
661                              'email',
662                              'phone',
663                              )
664                              },
665                      'StudentPume':
666                          {'id': 'pume',
667                           'title': 'Pume Data',
668                           'wf_state': 'close',
669                           'fields':
670                             ('pume_score',
671                              )
672                              },
673                      'StudentClearance':
674                          {'id': 'clearance',
675                           'title': 'Clearance Data',
676                           'wf_state': 'close',
677                           'fields':
678                             ('matric_no',
679                              'nationality',
680                              'lga',
681                              )
682                              },
683                         'StudentPersonal':
684                          {'id': 'personal',
685                           'title': 'Personal Data',
686                           'wf_state': 'close',
687                           'fields':
688                             ('firstname',
689                              'middlename',
690                              'lastname',
691                              'sex',
692                              'email',
693                              'phone',
694                              'perm_address',
695                              )
696                              },
697                         'StudentStudyCourse':
698                          {'id': 'study_course',
699                           'title': 'Study Course',
700                           'wf_state': 'close',
701                           'fields':
702                             ('study_course',
703                              'current_level',
704                              'current_session',
705                              'current_mode',
706                              'current_verdict',
707                              )
708                              },
709                         }
710    ###)
711
712
713    security.declareProtected(ModifyPortalContent,'import_student') ###(
714    def import_student(self,dict):
715        "create a students data"
716        logger = logging.getLogger('WAeUPTool.create_student')
717        students_folder = self.portal_url.getPortalObject().campus.students
718        jamb_reg_no = dict.get('jamb_reg_no',None)
719        if jamb_reg_no:
720            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
721            if res:
722                return '',"jamb_reg_no exists"
723        matric_no = dict.get('matric_no',None)
724        if matric_no:
725            res = self.students_catalog(matric_no = matric_no)
726            if res:
727                return '',"matric_no exists"
728        sid = self.waeup_tool.generateStudentId('?')
729        students_folder.invokeFactory('Student', sid)
730        student_obj = getattr(students_folder,sid)
731        f2t = self.student_field2types
732        for pt in f2t.keys():
733            student_obj.invokeFactory(pt,f2t[pt]['id'])
734            sub_obj = getattr(student_obj,f2t[pt]['id'])
735            sub_doc = sub_obj.getContent()
736            self.portal_workflow.doActionFor(sub_obj,'open',dest_container=sub_obj)
737            d = {'Title': f2t[pt]['title']}
738            for field in f2t[pt]['fields']:
739                d[field] = dict.get(field,'')
740            if pt == 'StudentPersonal':
741                d['sex'] = dict.get('sex') == 'F'
742            sub_doc.edit(mapping = d)
743            new_state = f2t[pt]['wf_state']
744            if new_state != "remain":
745                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
746        wfaction = 'return'
747        self.portal_workflow.doActionFor(student_obj,wfaction)
748        student_obj.manage_setLocalRoles(sid, ['Owner',])
749        return sid,''
750    ###)
751
752    security.declareProtected(ModifyPortalContent,"importData")###(
753    def importData(self,filename,name):
754        """load data from CSV values"""
755        import transaction
756        import random
757        logger = logging.getLogger('WAeUPTool.importData')
758        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
759        students_folder = self.portal_url.getPortalObject().campus.students
760        start = True
761        tr_count = 1
762        total_imported = 0
763        total_not_imported = 0
764        total = 0
765        iname = "import_%s" % name
766        stool = getToolByName(self, 'portal_schemas')
767        ltool = getToolByName(self, 'portal_layouts')
768        schema = stool._getOb(iname)
769        if schema is None:
770            em = 'No such schema import_%s' % iname
771            logger.error('No such schema import_%s' % iname)
772            return em
773        layout = ltool._getOb(iname)
774        if layout is None:
775            em = 'No such layout import_%s' % iname
776            logger.error(em)
777            return em
778        validators = {}
779        for widget in layout.keys():
780            validators[widget] = layout[widget].validate
781        creator = getattr(self, 'import_%s' % name,None)
782        if creator is None:
783            em = 'No creator function create_%s' % name
784            logger.error(em)
785            return em
786        not_imported = []
787        imported = []
788        try:
789            items = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
790        except:
791            em = 'Error reading %s.csv' % filename
792            logger.error(em)
793            return em
794        for item in items:
795            tr_count += 1
796            if start:
797                start = False
798                adapters = [MappingStorageAdapter(schema, item)]
799                dm = DataModel(item, adapters,context=self)
800                logger.info('Start importing from %s.csv' % filename)
801                import_keys = item.keys()
802                diff_set = set(import_keys).difference(set(schema.keys()))
803                if diff_set:
804                    logger.error('%s not in schema.' % diff_set)
805                    return
806                diff_set = set(import_keys).difference(set(layout.keys()))
807                if diff_set:
808                    logger.error('%s not in layout.' % diff_set)
809                    return
810                s = ','.join(['"%s"' % fn for fn in import_keys])
811                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
812                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write('%s,"Error"' %s + '\n')
813                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
814                format_error = format + ',"%(Error)s"'
815                #from pdb import set_trace; set_trace()
816                format = '"%(id)s",'+ format
817            ds = DataStructure(data=item,datamodel=dm)
818            error_string = ""
819            for k in import_keys:
820                if not validators[k](ds):
821                    error_string += " %s : %s" % (k,ds.getError(k))
822            if not error_string:
823                item.update(dm)
824                item['id'],error = creator(item)
825                if error:
826                    error_string += error
827            if error_string:
828                item['Error'] = error_string
829                not_imported.append(format_error % item)
830                total_not_imported += 1
831            else:
832                imported.append(format % item)
833                total_imported += 1
834            total += 1
835            if tr_count > 1000:
836                if len(not_imported) > 0:
837                    open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
838                             '\n'.join(not_imported) + '\n')
839                    not_imported = []
840                if len(imported) > 0:
841                    open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
842                             '\n'.join(not_imported) + '\n')
843                    imported = []
844                em = '%d transactions committed\n' % (tr_count)
845                transaction.commit()
846                regs = []
847                logger.info(em)
848                tr_count = 0
849        if len(imported) > 0:
850            open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
851                                                '\n'.join(imported))
852        if len(not_imported) > 0:
853            open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
854                                                '\n'.join(not_imported))
855        em = "Imported: %d, not imported: %d of total %d" % (total_imported,total_not_imported,total)
856        logger.info(em)
857        return em
858    ###)
859
860InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.