source: WAeUP_SRP/trunk/WAeUPTool.py @ 1798

Last change on this file since 1798 was 1798, checked in by Henrik Bettermann, 17 years ago

there are records with duplicate uid in online_payments_import which was not catched by the import function

  • Property svn:keywords set to Id
File size: 38.5 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 1798 2007-05-18 13:51:16Z 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            # format of the third file sent by Kehinde
626            data['datetime'] = date = 0
627            data['student_id'] = student_id = pay_transaction['customer_id']
628            data['order_id'] = order_id = pay_transaction['merchant_reference']
629            data['response_code'] = response_code = '00'
630            data['amount'] = amount = pay_transaction['Amount']           
631
632            dup = False
633            if response_code == "12":
634                continue
635            try:
636                opt.addRecord(**data)
637            except ValueError:
638                dup = True
639            #from pdb import set_trace;set_trace()
640            if dup:
641                if response_code == "00":
642                    try:
643                        opt.modifyRecord(**data)
644                    except:
645                        logger.info("duplicate uid, order_id %(order_id)s, student_id %(student_id)s, response_code %(response_code)s" % data)
646                        continue
647                else:
648                    pay_transaction['Error'] = "Duplicate order_id"
649                    no_import.append( format_error % pay_transaction)
650                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
651                    continue
652            tr_count += 1
653            if tr_count > 1000:
654                if len(no_import) > 0:
655                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
656                             '\n'.join(no_import) + '\n')
657                    no_import = []
658                em = '%d transactions committed\n' % (tr_count)
659                transaction.commit()
660                regs = []
661                logger.info(em)
662                total += tr_count
663                tr_count = 0
664        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
665                                                '\n'.join(no_import))
666        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
667    ###)
668
669
670    # all workflow transitions refer to students in state returning
671    student_field2types = {   ###(
672                      'StudentApplication':
673                          {'id': 'application',
674                           'title': 'Application Data',
675                           'wf_transition': 'close',
676                           'fields':
677                             ('jamb_reg_no',
678                              'entry_mode',
679                              'entry_session',
680                              'jamb_score',
681                              'app_email',
682                              )
683                              },
684                      #'StudentPume':
685                      #    {'id': 'pume',
686                      #     'title': 'Pume Data',
687                      #     'wf_transition': 'close',
688                      #     'fields':
689                      #       ('pume_score',
690                      #        )
691                      #        },
692                      'StudentClearance':
693                          {'id': 'clearance',
694                           'title': 'Clearance Data',
695                           'wf_transition': 'close',
696                           'fields':
697                             ('matric_no',
698                              'nationality',
699                              'lga',
700                              )
701                              },
702                         'StudentPersonal':
703                          {'id': 'personal',
704                           'title': 'Personal Data',
705                           'wf_transition': 'open',
706                           'fields':
707                             ('firstname',
708                              'middlename',
709                              'lastname',
710                              'sex',
711                              'email',
712                              'phone',
713                              'perm_address',
714                              )
715                              },
716                         'StudentStudyCourse':
717                          {'id': 'study_course',
718                           'title': 'Study Course',
719                           'wf_transition': 'open',
720                           'fields':
721                             ('study_course',
722                              'current_level',
723                              'current_session',
724                              'current_mode',
725                              'current_verdict',
726                              )
727                              },
728                         'PaymentsFolder':
729                          {'id': 'payments',
730                           'title': 'Payments',
731                           'wf_transition': 'open',
732                           'fields':
733                             ()
734                              },
735                         }
736    ###)
737
738
739    security.declareProtected(ModifyPortalContent,'importStudent') ###(
740    def importStudent(self,dict):
741        "create a students record due import"
742        logger = logging.getLogger('WAeUPTool.importStudent')
743        students_folder = self.portal_url.getPortalObject().campus.students
744        jamb_reg_no = dict.get('jamb_reg_no',None)
745        if jamb_reg_no:
746            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
747            if res:
748                return '',"jamb_reg_no exists"
749        matric_no = dict.get('matric_no',None)
750        if matric_no:
751            res = self.students_catalog(matric_no = matric_no)
752            if res:
753                return '',"matric_no exists"
754        sid = self.waeup_tool.generateStudentId('?')
755        students_folder.invokeFactory('Student', sid)
756        student_obj = getattr(students_folder,sid)
757        f2t = self.student_field2types
758        d = {}
759        d['jamb_sex']  = 'M'
760        if dict.get('sex'):
761            d['jamb_sex']  = 'F'
762        for pt in f2t.keys():
763            student_obj.invokeFactory(pt,f2t[pt]['id'])
764            sub_obj = getattr(student_obj,f2t[pt]['id'])
765            sub_doc = sub_obj.getContent()
766            d['Title'] = f2t[pt]['title']
767            for field in f2t[pt]['fields']:
768                d[field] = dict.get(field,'')
769            sub_doc.edit(mapping = d)
770            new_state = f2t[pt]['wf_transition']
771            if new_state != "remain":
772                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
773        wfaction = 'return'
774        self.portal_workflow.doActionFor(student_obj,wfaction)
775        student_obj.manage_setLocalRoles(sid, ['Owner',])
776        return sid,''
777    ###)
778
779    security.declareProtected(ModifyPortalContent,'importEditStudent') ###(
780    def importEditStudent(self,dict):
781        "edit a students record due import"
782        logger = logging.getLogger('WAeUPTool.importEditStudent')
783        students_folder = self.portal_url.getPortalObject().campus.students
784        sid = dict.get('id',None)
785        jamb_reg_no = dict.get('jamb_reg_no',None)
786        matric_no = dict.get('matric_no',None)
787        if sid:
788            res = self.students_catalog(id = sid)
789            if not res:
790                return '',"no student with id %s" % sid
791            elif matric_no and res[0].matric_no and\
792              matric_no != res[0].matric_no:
793                return '%s' % res[0].id ,"student has no matric_no %s" % matric_no
794            elif jamb_reg_no and res[0].jamb_reg_no and\
795              jamb_reg_no != res[0].jamb_reg_no:
796                return '%s' % res[0].id ,"student has no jamb_reg_no %s" % jamb_reg_no
797        elif matric_no:
798            res = self.students_catalog(matric_no = matric_no)
799            if not res:
800                return '',"no student with matric_no %s" % matric_no
801            elif jamb_reg_no and res[0].jamb_reg_no and\
802              jamb_reg_no != res[0].jamb_reg_no:
803                return '%s' % res[0].id ,"student has no jamb_reg_no %s" % jamb_reg_no
804        elif jamb_reg_no:
805            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
806            if not res:
807                return '',"no student with jamb_reg_no %s" % jamb_reg_no
808        sid = res[0].id
809        student_obj = getattr(students_folder,sid)
810        f2t = self.student_field2types
811        d = {}
812        d['jamb_sex']  = 'M'
813        if dict.get('sex'):
814            d['jamb_sex']  = 'F'
815        for pt in f2t.keys():
816            sub_obj = getattr(student_obj,f2t[pt]['id'],None)
817            if sub_obj is None:
818                try:
819                    student_obj.invokeFactory(pt,f2t[pt]['id'])
820                except:
821                    continue
822                sub_obj = getattr(student_obj,f2t[pt]['id'])
823            sub_doc = sub_obj.getContent()
824            # self.portal_workflow.doActionFor(sub_obj,'open',dest_container=sub_obj)
825            d['Title'] = f2t[pt]['title']
826            for field in f2t[pt]['fields']:
827                d[field] = dict.get(field,'')
828            sub_doc.edit(mapping = d)
829            # new_state = f2t[pt]['wf_transition']
830            # if new_state != "remain":
831            #     self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
832        # wfaction = 'return'
833        # self.portal_workflow.doActionFor(student_obj,wfaction)
834        # student_obj.manage_setLocalRoles(sid, ['Owner',])
835        return sid,''
836    ###)
837
838    security.declareProtected(ModifyPortalContent,"importData")###(
839    def importData(self,filename,name,edit=False):
840        """load data from CSV values"""
841        import transaction
842        import random
843
844        pm = self.portal_membership
845        member = pm.getAuthenticatedMember()
846
847        logger = logging.getLogger('WAeUPTool.importData')
848        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
849        students_folder = self.portal_url.getPortalObject().campus.students
850        start = True
851        tr_count = 1
852        total_imported = 0
853        total_not_imported = 0
854        total = 0
855        iname = "import_%s" % name
856        stool = getToolByName(self, 'portal_schemas')
857        ltool = getToolByName(self, 'portal_layouts')
858        schema = stool._getOb(iname)
859        if schema is None:
860            em = 'No such schema %s' % iname
861            logger.error('No such schema %s' % iname)
862            return em
863        layout = ltool._getOb(iname)
864        if layout is None:
865            em = 'No such layout %s' % iname
866            logger.error(em)
867            return em
868        validators = {}
869        for widget in layout.keys():
870            validators[widget] = layout[widget].validate
871        if edit:
872            importer_name = "importEdit%s" % name.capitalize()
873        else:
874            importer_name = "import%s" % name.capitalize()
875        importer = getattr(self, '%s' % importer_name,None)
876        if importer is None:
877            em = 'No importer function %s' % importer_name
878            logger.error(em)
879            return em
880        not_imported = []
881        imported = []
882        try:
883            items = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
884        except:
885            em = 'Error reading %s.csv' % filename
886            logger.error(em)
887            return em
888        for item in items:
889            tr_count += 1
890            if start:
891                start = False
892                adapters = [MappingStorageAdapter(schema, item)]
893                dm = DataModel(item, adapters,context=self)
894                logger.info('%s starts import from %s.csv' % (member,filename))
895                import_keys = item.keys()
896                diff_set = set(import_keys).difference(set(schema.keys()))
897                if diff_set:
898                    logger.error('%s not in schema.' % diff_set)
899                    return
900                diff_set = set(import_keys).difference(set(layout.keys()))
901                if diff_set:
902                    logger.error('%s not in layout.' % diff_set)
903                    return
904                s = ','.join(['"%s"' % fn for fn in import_keys])
905                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(s + ',"Error"'+ '\n')
906                s = '"id",' + s
907                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
908                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
909                format_error = format + ',"%(Error)s"'
910                format = '"%(id)s",'+ format
911            ds = DataStructure(data=item,datamodel=dm)
912            error_string = ""
913            for k in import_keys:
914                if not validators[k](ds):
915                    error_string += " %s : %s" % (k,ds.getError(k))
916            if not error_string:
917                item.update(dm)
918                item['id'],error = importer(item)
919                if error:
920                    error_string += error
921            if error_string:
922                item['Error'] = error_string
923                not_imported.append(format_error % item)
924                total_not_imported += 1
925            else:
926                imported.append(format % item)
927                total_imported += 1
928            total += 1
929            if tr_count > 1000:
930                if len(not_imported) > 0:
931                    open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
932                             '\n'.join(not_imported) + '\n')
933                    not_imported = []
934                if len(imported) > 0:
935                    open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
936                             '\n'.join(imported) + '\n')
937                    imported = []
938                em = '%d transactions committed\n' % (tr_count)
939                transaction.commit()
940                regs = []
941                logger.info(em)
942                tr_count = 0
943        if len(imported) > 0:
944            open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
945                                                '\n'.join(imported))
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))
949        em = "Imported: %d, not imported: %d of total %d" % (total_imported,total_not_imported,total)
950        logger.info(em)
951        return em
952    ###)
953
954InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.