source: WAeUP_SRP/trunk/WAeUPTool.py @ 1819

Last change on this file since 1819 was 1818, checked in by joachim, 17 years ago

fix undefined matric_no in loadStudentFoto

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