source: WAeUP_SRP/trunk/WAeUPTool.py @ 1797

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

ticket #211

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