source: WAeUP_SRP/trunk/WAeUPTool.py @ 1774

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

add importEdit (untested)

  • Property svn:keywords set to Id
File size: 37.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 1774 2007-05-11 15:33:54Z 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        #from pdb import set_trace; set_trace()
207        d = {}
208        d['jamb_sex']  = 'M'
209        if dict.get('sex'):
210            d['jamb_sex']  = 'F'
211        for pt in f2t.keys():
212            student_obj.invokeFactory(pt,f2t[pt]['id'])
213            sub_obj = getattr(student_obj,f2t[pt]['id'])
214            sub_doc = sub_obj.getContent()
215            self.portal_workflow.doActionFor(sub_obj,'open',dest_container=sub_obj)
216            d['Title'] = f2t[pt]['title']
217            for field in f2t[pt]['fields']:
218                d[field] = dict.get(field,'')
219            sub_doc.edit(mapping = d)
220            new_state = f2t[pt]['wf_state']
221            if new_state != "remain":
222                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
223        entry_session = dict.get('entry_session')
224        wfaction = 'return'
225        if entry_session == self.getSessionId():
226            wfaction = 'admit'
227        self.portal_workflow.doActionFor(student_obj,wfaction)
228        student_obj.manage_setLocalRoles(sid, ['Owner',])
229        return sid,password
230    ###)
231
232    security.declarePublic('getCertificateBrain') ###(
233    def getCertificateBrain(self,cert_id):
234        "do it"
235        res = ZCatalog.searchResults(self.portal_catalog,
236                                {'portal_type':"Certificate",
237                                      'id': cert_id})
238        if res:
239            return res[0]
240        return None
241    ###)
242
243    security.declareProtected(ModifyPortalContent,'get_csv_filenames') ###(
244    def get_csv_filenames(self):
245        "do it"
246        files = [file for file in os.listdir("%s/import/" % (i_home))
247                 if file.endswith('.csv') and file.find('imported') == -1]
248        return files
249    ###)
250
251    security.declarePublic('findStudentByMatricelNo') ###(
252    def findStudentByMatricelNo(self,matric_no):
253        "do it"
254        res = ZCatalog.searchResults(self.portal_catalog,
255                                {'portal_type':"StudentClearance",
256                                 'SearchableText': matric_no})
257        if res:
258            return res[0]
259        return None
260    ###)
261
262    security.declarePublic('makeStudentMember') ###(
263    def makeStudentMember(self,sid,password='uNsEt'):
264        """make the student a member"""
265        membership = self.portal_membership
266        membership.addMember(sid,
267                             password ,
268                             roles=('Member',
269                                     'Student',
270                                     ),
271                             domains='',
272                             properties = {'memberareaCreationFlag': False,
273                                           'homeless': True},)
274        member = membership.getMemberById(sid)
275        self.portal_registration.afterAdd(member, sid, password, None)
276        #self.manage_setLocalRoles(sid, ['Owner',])
277    ###)
278
279    security.declarePublic('makeStudentData') ###(
280    def makeStudentData(self,student_id,email=None,phone_nr=None):
281        "create Datastructure for a returning Student"
282        #import pdb;pdb.set_trace()
283        logger = logging.getLogger('WAeUPTool.makeStudentData')
284        students_folder = self.portal_url.getPortalObject().campus.students
285        res = self.students_catalog(id=student_id)
286        if res:
287            st = res[0]
288        res = self.returning_import(matric_no = st.matric_no)
289        if res:
290            student = res[0]
291        logger.info('%s creates data structure' % student_id)
292        s_results = self.results_import(matric_no = st.matric_no)
293        lnr = self.getLevelFromResultsCosCode(s_results)
294        level = "%d00" % lnr
295        verdict,eligible = self.getVerdict(s_results[0].Verdict)
296        if eligible:
297            level = "%d00" % (lnr + 1)
298##        level = s_results[0].Level
299##        for result in s_results:
300##            if level != result.Level:
301##                logger.info('"%s", "Levels differ","%s != %s"' % (student_id,level,result.Level))
302        #student should not be allowed to perform this transition
303        #wftool = self.portal_workflow
304        #wftool.doActionFor(student,'return')
305        certcode_org = student.Coursemajorcode
306        certcode = makeCertificateCode(certcode_org)
307        certificate_brain = self.getCertificateBrain(certcode)
308        if not certificate_brain:
309            em = 'Certificate %s org-code %s not found\n' % (certcode, certcode_org)
310            logger.info(em)
311        matric_no = student.matric_no
312        sid = student_id
313        student_obj = getattr(students_folder,sid)
314        student_obj.invokeFactory('StudentApplication','application')
315        application = student_obj.application
316        self.portal_workflow.doActionFor(application,'open',dest_container=application)
317        da = {'Title': 'Application Data'}
318        student_obj.invokeFactory('StudentPersonal','personal')
319        da['jamb_reg_no'] = student.Entryregno
320        em = self.getEntryMode(student.Entryregno)
321##        em = student.Mode_of_Entry
322##        if em in ('DIRECT', 'DIRECT ENTRY',):
323##            em = 'DE'
324##        elif em in ('U.M.E', 'UNE',):
325##            em = 'UME'
326##        elif not em:
327##            em = "unknown"
328        da['entry_mode'] = em
329        personal = student_obj.personal
330        self.portal_workflow.doActionFor(personal,'open',dest_container=personal)
331        dp = {'Title': 'Personal Data'}
332        student_obj.invokeFactory('StudentClearance','clearance')
333        clearance = student_obj.clearance
334        self.portal_workflow.doActionFor(clearance,'open',dest_container=clearance)
335        dc = {'Title': 'Clearance/Eligibility Record'}
336        dc['matric_no'] = matric_no
337        state = student.State
338        lga = student.LGA
339        if state and lga:
340            lga =  state + ' / ' + lga
341        else:
342            lga = "None"
343        da['jamb_lga'] = dc['lga'] = lga
344        da['app_email'] = dp['email'] = email
345        da['app_mobile'] = dp['phone'] = phone_nr
346        dp['firstname'] = student.Firstname
347        dp['middlename'] = student.Middlename
348        dp['lastname'] = student.Lastname
349        da['jamb_lastname'] = "%s %s %s" % (student.Firstname,student.Middlename,student.Lastname)
350        da['jamb_sex'] = student.Sex
351        dp['sex'] = student.Sex == 'F'
352        dp['perm_address'] = student.Permanent_Address
353        application.getContent().edit(mapping=da)
354        self.portal_workflow.doActionFor(application,'close',dest_container=application)
355        personal.getContent().edit(mapping=dp)
356        clearance.getContent().edit(mapping=dc)
357        self.portal_workflow.doActionFor(clearance,'close',dest_container=clearance)
358##        catd = {}
359##        catd['id'] = sid
360##        catd['entry_mode']= da['entry_mode']
361##        catd['matric_no'] = matric_no
362##        catd['jamb_reg_no'] = da['jamb_reg_no']
363##        catd['name'] = "%(firstname)s %(middlename)s %(lastname)s" % dp
364##        catd['sex'] = dp['sex']
365##        catd['level'] = level
366##        catd['verdict'] = verdict
367##        if certificate_brain:
368##            cpath = certificate_brain.getPath().split('/')
369##            catd['faculty'] = cpath[-4]
370##            catd['department'] = cpath[-3]
371##            catd['course'] = certcode
372##        self.students_catalog.modifyRecord(**catd)
373        #
374        # Study Course
375        #
376        student_obj.invokeFactory('StudentStudyCourse','study_course')
377        studycourse = student_obj.study_course
378        self.portal_workflow.doActionFor(studycourse,'open',dest_container=studycourse)
379        dsc = {}
380        dsc['study_course'] = certcode
381        dsc['current_level'] = level
382        dsc['current_verdict'] = verdict
383        dsc['current_session'] = '06'
384        studycourse.getContent().edit(mapping=dsc)
385        #
386        # Level
387        #
388##        l = getattr(studycourse,level,None)
389##        if l is None:
390##            studycourse.invokeFactory('StudentStudyLevel', level)
391##            l = getattr(studycourse, level)
392##            self.portal_workflow.doActionFor(l,'open',dest_container=l)
393##            l.getContent().edit(mapping={'Title': "Level %s" % level})
394###)
395
396    security.declarePublic('makeStudentLevel') ###(
397    def makeStudentLevel(self,student_id):
398        "create the StudyLevel for a returning Student"
399        #import pdb;pdb.set_trace()
400        logger = logging.getLogger('WAeUPTool.makeStudentLevel')
401        students_folder = self.portal_url.getPortalObject().campus.students
402        res = self.students_catalog(id=student_id)
403        if res:
404            st = res[0]
405        course = st.course
406        matric_no = st.matric_no
407        level = st.level
408        res = self.results_import(matric_no = matric_no)
409        if res:
410            results = res
411        logger.info('%s creating Level %s' % (student_id,level))
412        #
413        # Level
414        #
415        student_obj = getattr(self.portal_url.getPortalObject().campus.students,student_id)
416        studycourse = getattr(student_obj,"study_course",None)
417        self.portal_workflow.doActionFor(studycourse,'close_for_edit',dest_container=studycourse)
418        l = getattr(studycourse,level,None)
419        if l is None:
420            studycourse.invokeFactory('StudentStudyLevel', level)
421            l = getattr(studycourse, level)
422            self.portal_workflow.doActionFor(l,'open',dest_container=l)
423            l.getContent().edit(mapping={'Title': "Level %s" % level})
424        ###)
425
426    security.declarePublic('getAccommodationInfo') ###(
427    def getAccommodationInfo(self,bed):
428        """return Accommodation Info"""
429        info = {}
430        hall,block,room,letter = bed.split('_')
431        res = ZCatalog.searchResults(self.portal_catalog,portal_type="AccoHall",id=hall)
432        if res and len(res) == 1:
433            hall_brain = res[0]
434            hall_doc = hall_brain.getObject().getContent()
435        else:
436            return info
437        info['hall_title'] = hall_brain.Title
438        info['maintenance_code'] = hall_doc.maintenance_code
439        res = ZCatalog.searchResults(self.portal_catalog,portal_type="ScratchCardBatch")
440        batch_doc = None
441        for brain in res:
442            if brain.id.startswith(info['maintenance_code']):
443                batch_doc = brain.getObject().getContent()
444                break
445        if batch_doc is None:
446            info['maintenance_fee'] = None
447        else:
448            info['maintenance_fee'] = batch_doc.cost
449        return info
450    ###)
451
452    security.declareProtected(ModifyPortalContent,'deleteAllCourses') ###(
453    def deleteAllCourses(self,department="All"):
454        ''' delete the courses'''
455        pm = self.portal_membership
456        member = pm.getAuthenticatedMember()
457
458        if str(member) not in ("henrik","joachim"):
459            return "not possible"
460        if department == "All":
461            res = self.portal_catalog({'meta_type': 'Department'})
462        if len(res) < 1:
463            return "No Departments found"
464
465        deleted = []
466        for dep in res:
467            cf = dep.getObject().courses
468            if cf:
469                cf.manage_delObjects(ids=cf.objectIds())
470                deleted.append("deleted Courses in %s" % dep.getId)
471        return "\r".join(deleted)
472    ###)
473
474    security.declareProtected(ModifyPortalContent,'getLogfileLines') ###(
475    def getLogfileLines(self,filename="event.log",numlines=20):
476        """Get last NUMLINES lines of logfile FILENAME.
477
478        Return last lines' of a file in the instances logfile directory as
479        a list. The number of returned lines equals `numlines' or less. If
480        less than `numlines' lines are available, the whole file ist
481        returned. If the file can not be opened or some other error
482        occurs, empty list is returend.
483        """
484        result = []
485        lines_hit = 0
486
487        # We only handle files in instances' log directory...
488        logpath = os.path.join(i_home, "log")
489        filename = str(os.path.abspath( os.path.join( logpath, filename )))
490        if not filename.startswith( logpath ):
491            # Attempt to access file outside log-dir...
492            return []
493
494        try:
495            fd = file( filename, "rb" )
496        except IOError:
497            return []
498        if not fd:
499            return []
500
501        if os.linesep == None:
502            linesep = '\n'
503        else:
504            linesep = os.linesep
505
506        # Try to find 'numlines' times a lineseparator, searching from end
507        # and moving to the beginning of file...
508        fd.seek( 0, 2) # Move to end of file...
509        while lines_hit < numlines:
510            if fd.read(1) == linesep[-1]: # This moves filedescriptor
511                                          # one step forward...
512                lines_hit += 1
513            try:
514                fd.seek( -2, 1) # Go two bytes back from current pos...
515            except IOError:
516                # We cannot go back two bytes. Maybe the file is too small...
517                break
518        fd.seek(2,1)
519
520        # Read all lines from current position...
521        result = fd.readlines()
522        # Remove line endings...
523        result = [x.strip() for x in result]
524        fd.close()
525        return result
526    ###)
527
528    security.declareProtected(ModifyPortalContent,"getCallbacksFromLog")###(
529    def getCallbacksFromLog(self,filename):
530        """fix Online Payment Transactions from Z2.log entries"""
531        import transaction
532        import random
533        from cgi import parse_qs
534        from urlparse import urlparse
535        #from pdb import set_trace
536        wftool = self.portal_workflow
537        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
538        students_folder = self.portal_url.getPortalObject().campus.students
539        s = r'(?P<client_ip>\S+) - (?P<member_id>\S+) \['
540        s += r'(?P<date>.*)\] "(?P<get>.*)" (?P<codes>\d+ \d+) "'
541        s += r'(?P<intersw>.*)" "(?P<agent>.*)"'
542        data = re.compile(s)
543        start = True
544        tr_count = 1
545        total = 0
546        #name = 'pume_results'
547        #name = 'epaymentsuccessful_z2log2'
548        name = filename
549        no_import = []
550        imported = []
551        logger = logging.getLogger('WAeUPTool.getFailedTransactions')
552        try:
553            transactions = open("%s/import/%s" % (i_home,name),"rb").readlines()
554        except:
555            logger.error('Error reading %s' % name)
556            return
557        tas = []
558        for line in transactions:
559            dict = {}
560            items = data.search(line)
561            dict['idict'] = idict = items.groupdict()
562            #print idict
563            #from pdb import set_trace;set_trace()
564            urlparsed = urlparse(idict['get'][4:])
565            #print urlparsed
566            path = urlparsed[2].split('/')
567            dict['student_id'] = student_id = path[8]
568            dict['payment_id'] = payment_id = path[10]
569            dict['qs_dict'] = qs_dict = parse_qs(urlparsed[4])
570            tas.append(dict)
571            tr_count += 1
572        return tas
573    ###)
574
575    security.declareProtected(ModifyPortalContent,"importOnlinePaymentTransactions")###(
576    def importOnlinePaymentTransactions(self):
577        """load Online Payment Transactions from CSV values"""
578        import transaction
579        import random
580        #from pdb import set_trace
581        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
582        opt = self.online_payments_import
583        students_folder = self.portal_url.getPortalObject().campus.students
584        start = True
585        tr_count = 1
586        total = 0
587        #name = 'pume_results'
588        name = 'OnlineTransactions'
589        no_import = []
590        imported = []
591        logger = logging.getLogger('WAeUPTool.importOnlinePaymentTransactions')
592        try:
593            transactions = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
594        except:
595            logger.error('Error reading %s.csv' % name)
596            return
597        for pay_transaction in transactions:
598            if start:
599                start = False
600                logger.info('Start loading from %s.csv' % name)
601                s = ','.join(['"%s"' % fn for fn in pay_transaction.keys()])
602                no_import.append('%s,"Error"' % s)
603                format = ','.join(['"%%(%s)s"' % fn for fn in pay_transaction.keys()])
604                format_error = format + ',"%(Error)s"'
605            data = {}
606
607            # format of the first file sent from Tayo
608            #data['datetime'] = date = DateTime.DateTime(pay_transaction['Date'])
609            #data['student_id'] = student_id = pay_transaction['Payer ID']
610            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
611            #data['response_code'] = response_code = pay_transaction['Resp Code']
612            #data['amount'] = amount = pay_transaction['Amount']
613
614            # format of the second file sent from Tayo
615            data['datetime'] = date = 0
616            data['student_id'] = student_id = pay_transaction['Payer ID']
617            data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
618            data['response_code'] = response_code = '00'
619            data['amount'] = amount = pay_transaction['Amount']
620
621            dup = False
622            if response_code == "12":
623                continue
624            try:
625                opt.addRecord(**data)
626            except ValueError:
627                dup = True
628            #from pdb import set_trace;set_trace()
629            if dup:
630                if response_code == "00":
631                    opt.modifyRecord(**data)
632                else:
633                    pay_transaction['Error'] = "Duplicate order_id"
634                    no_import.append( format_error % pay_transaction)
635                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
636                    continue
637            tr_count += 1
638            if tr_count > 1000:
639                if len(no_import) > 0:
640                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
641                             '\n'.join(no_import) + '\n')
642                    no_import = []
643                em = '%d transactions committed\n' % (tr_count)
644                transaction.commit()
645                regs = []
646                logger.info(em)
647                total += tr_count
648                tr_count = 0
649        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
650                                                '\n'.join(no_import))
651        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
652    ###)
653
654    student_field2types = {   ###(
655                      'StudentApplication':
656                          {'id': 'application',
657                           'title': 'Application Data',
658                           'wf_state': 'close',
659                           'fields':
660                             ('jamb_reg_no',
661                              'entry_mode',
662                              'entry_session',
663                              'jamb_score',
664                              'email',
665                              'phone',
666                              )
667                              },
668                      'StudentPume':
669                          {'id': 'pume',
670                           'title': 'Pume Data',
671                           'wf_state': 'close',
672                           'fields':
673                             ('pume_score',
674                              )
675                              },
676                      'StudentClearance':
677                          {'id': 'clearance',
678                           'title': 'Clearance Data',
679                           'wf_state': 'close',
680                           'fields':
681                             ('matric_no',
682                              'nationality',
683                              'lga',
684                              )
685                              },
686                         'StudentPersonal':
687                          {'id': 'personal',
688                           'title': 'Personal Data',
689                           'wf_state': 'close',
690                           'fields':
691                             ('firstname',
692                              'middlename',
693                              'lastname',
694                              'sex',
695                              'email',
696                              'phone',
697                              'perm_address',
698                              )
699                              },
700                         'StudentStudyCourse':
701                          {'id': 'study_course',
702                           'title': 'Study Course',
703                           'wf_state': 'close',
704                           'fields':
705                             ('study_course',
706                              'current_level',
707                              'current_session',
708                              'current_mode',
709                              'current_verdict',
710                              )
711                              },
712                         }
713    ###)
714
715
716    security.declareProtected(ModifyPortalContent,'importStudent') ###(
717    def importStudent(self,dict):
718        "create a students data"
719        logger = logging.getLogger('WAeUPTool.import_student')
720        students_folder = self.portal_url.getPortalObject().campus.students
721        jamb_reg_no = dict.get('jamb_reg_no',None)
722        if jamb_reg_no:
723            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
724            if res:
725                return '',"jamb_reg_no exists"
726        matric_no = dict.get('matric_no',None)
727        if matric_no:
728            res = self.students_catalog(matric_no = matric_no)
729            if res:
730                return '',"matric_no exists"
731        sid = self.waeup_tool.generateStudentId('?')
732        students_folder.invokeFactory('Student', sid)
733        student_obj = getattr(students_folder,sid)
734        f2t = self.student_field2types
735        d = {}
736        d['jamb_sex']  = 'M'
737        if dict.get('sex'):
738            d['jamb_sex']  = 'F'
739        for pt in f2t.keys():
740            student_obj.invokeFactory(pt,f2t[pt]['id'])
741            sub_obj = getattr(student_obj,f2t[pt]['id'])
742            sub_doc = sub_obj.getContent()
743            self.portal_workflow.doActionFor(sub_obj,'open',dest_container=sub_obj)
744            d['Title'] = f2t[pt]['title']
745            for field in f2t[pt]['fields']:
746                d[field] = dict.get(field,'')
747            sub_doc.edit(mapping = d)
748            new_state = f2t[pt]['wf_state']
749            if new_state != "remain":
750                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
751        wfaction = 'return'
752        self.portal_workflow.doActionFor(student_obj,wfaction)
753        student_obj.manage_setLocalRoles(sid, ['Owner',])
754        return sid,''
755    ###)
756
757    security.declareProtected(ModifyPortalContent,'importEditStudent') ###(
758    def importEditStudent(self,dict):
759        "edit a students data"
760        logger = logging.getLogger('WAeUPTool.create_student')
761        students_folder = self.portal_url.getPortalObject().campus.students
762        sid = dict.get('id',None)
763        jamb_reg_no = dict.get('jamb_reg_no',None)
764        matric_no = dict.get('matric_no',None)
765        if sid:
766            res = self.students_catalog(id = sid)
767            if not res:
768                return '',"no student with id %s" % sid
769            elif matric_no and res[0].matric_no and\
770              matric_no != res[0].matric_no:
771                return '%s' % res[0].id ,"student has no matric_no %s" % matric_no
772            elif jamb_reg_no and res[0].jamb_reg_no and\
773              jamb_reg_no != res[0].jamb_reg_no:
774                return '%s' % res[0].id ,"student has no jamb_reg_no %s" % jamb_reg_no
775        elif matric_no:
776            res = self.students_catalog(matric_no = matric_no)
777            if not res:
778                return '',"no student with matric_no %s" % matric_no
779            elif jamb_reg_no and res[0].jamb_reg_no and\
780              jamb_reg_no != res[0].jamb_reg_no:
781                return '%s' % res[0].id ,"student has no jamb_reg_no %s" % jamb_reg_no
782        elif jamb_reg_no:
783            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
784            if not res:
785                return '',"no student with jamb_reg_no %s" % jamb_reg_no
786        sid = res[0].id
787        student_obj = getattr(students_folder,sid)
788        f2t = self.student_field2types
789        d = {}
790        d['jamb_sex']  = 'M'
791        if dict.get('sex'):
792            d['jamb_sex']  = 'F'
793        for pt in f2t.keys():
794            sub_obj = getattr(student_obj,f2t[pt]['id'],None)
795            if sub_obj is None:
796                student_obj.invokeFactory(pt,f2t[pt]['id'])
797                sub_obj = getattr(student_obj,f2t[pt]['id'])
798            sub_doc = sub_obj.getContent()
799            self.portal_workflow.doActionFor(sub_obj,'open',dest_container=sub_obj)
800            d['Title'] = f2t[pt]['title']
801            for field in f2t[pt]['fields']:
802                d[field] = dict.get(field,'')
803            sub_doc.edit(mapping = d)
804            # new_state = f2t[pt]['wf_state']
805            # if new_state != "remain":
806            #     self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
807        # wfaction = 'return'
808        # self.portal_workflow.doActionFor(student_obj,wfaction)
809        # student_obj.manage_setLocalRoles(sid, ['Owner',])
810        return sid,''
811    ###)
812
813    security.declareProtected(ModifyPortalContent,"importData")###(
814    def importData(self,filename,name,edit=False):
815        """load data from CSV values"""
816        import transaction
817        import random
818       
819        pm = self.portal_membership
820        member = pm.getAuthenticatedMember()       
821       
822        logger = logging.getLogger('WAeUPTool.importData')
823        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
824        students_folder = self.portal_url.getPortalObject().campus.students
825        start = True
826        tr_count = 1
827        total_imported = 0
828        total_not_imported = 0
829        total = 0
830        iname = "import_%s" % name
831        stool = getToolByName(self, 'portal_schemas')
832        ltool = getToolByName(self, 'portal_layouts')
833        schema = stool._getOb(iname)
834        if schema is None:
835            em = 'No such schema %s' % iname
836            logger.error('No such schema %s' % iname)
837            return em
838        layout = ltool._getOb(iname)
839        if layout is None:
840            em = 'No such layout %s' % iname
841            logger.error(em)
842            return em
843        validators = {}
844        for widget in layout.keys():
845            validators[widget] = layout[widget].validate
846        if edit:
847            importer_name = "importEdit%s" % name.capitalize()
848        else:
849            importer_name = "import%s" % name.capitalize()
850        importer = getattr(self, '%s' % importer_name,None)
851        if importer is None:
852            em = 'No importer function %s' % importer_name
853            logger.error(em)
854            return em
855        not_imported = []
856        imported = []
857        try:
858            items = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
859        except:
860            em = 'Error reading %s.csv' % filename
861            logger.error(em)
862            return em
863        for item in items:
864            tr_count += 1
865            if start:
866                start = False
867                adapters = [MappingStorageAdapter(schema, item)]
868                dm = DataModel(item, adapters,context=self)
869                logger.info('%s starts import from %s.csv' % (member,filename))
870                import_keys = item.keys()
871                diff_set = set(import_keys).difference(set(schema.keys()))
872                if diff_set:
873                    logger.error('%s not in schema.' % diff_set)
874                    return
875                diff_set = set(import_keys).difference(set(layout.keys()))
876                if diff_set:
877                    logger.error('%s not in layout.' % diff_set)
878                    return
879                s = ','.join(['"%s"' % fn for fn in import_keys])
880                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(s + ',"Error"'+ '\n')
881                s = '"id",' + s
882                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
883                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
884                format_error = format + ',"%(Error)s"'
885                format = '"%(id)s",'+ format
886            ds = DataStructure(data=item,datamodel=dm)
887            error_string = ""
888            for k in import_keys:
889                if not validators[k](ds):
890                    error_string += " %s : %s" % (k,ds.getError(k))
891            if not error_string:
892                item.update(dm)
893                item['id'],error = importer(item)
894                if error:
895                    error_string += error
896            if error_string:
897                item['Error'] = error_string
898                not_imported.append(format_error % item)
899                total_not_imported += 1
900            else:
901                imported.append(format % item)
902                total_imported += 1
903            total += 1
904            if tr_count > 1000:
905                if len(not_imported) > 0:
906                    open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
907                             '\n'.join(not_imported) + '\n')
908                    not_imported = []
909                if len(imported) > 0:
910                    open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
911                             '\n'.join(imported) + '\n')
912                    imported = []
913                em = '%d transactions committed\n' % (tr_count)
914                transaction.commit()
915                regs = []
916                logger.info(em)
917                tr_count = 0
918        if len(imported) > 0:
919            open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
920                                                '\n'.join(imported))
921        if len(not_imported) > 0:
922            open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
923                                                '\n'.join(not_imported))
924        em = "Imported: %d, not imported: %d of total %d" % (total_imported,total_not_imported,total)
925        logger.info(em)
926        return em
927    ###)
928
929InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.