source: WAeUP_SRP/trunk/WAeUPTool.py @ 1813

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

reload picture of late admissions after login
Joachim, please check!

  • 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 1813 2007-05-23 19:23:45Z 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,filename,folder):
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/%s/%s.jpg" % (i_home,folder,filename)
159        picture2 ="%s/import/%s/%s.JPG" % (i_home,folder,filename)
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                              'birthday',
701                              )
702                              },
703                         'StudentPersonal':
704                          {'id': 'personal',
705                           'title': 'Personal Data',
706                           'wf_transition': 'open',
707                           'fields':
708                             ('firstname',
709                              'middlename',
710                              'lastname',
711                              'sex',
712                              'email',
713                              'phone',
714                              'perm_address',
715                              )
716                              },
717                         'StudentStudyCourse':
718                          {'id': 'study_course',
719                           'title': 'Study Course',
720                           'wf_transition': 'open',
721                           'fields':
722                             ('study_course',
723                              'current_level',
724                              'current_session',
725                              'current_mode',
726                              'current_verdict',
727                              )
728                              },
729                         'PaymentsFolder':
730                          {'id': 'payments',
731                           'title': 'Payments',
732                           'wf_transition': 'open',
733                           'fields':
734                             ()
735                              },
736                         }
737    ###)
738
739
740    security.declareProtected(ModifyPortalContent,'importStudent') ###(
741    def importStudent(self,dict):
742        "create a students record due import"
743        logger = logging.getLogger('WAeUPTool.importStudent')
744        students_folder = self.portal_url.getPortalObject().campus.students
745        jamb_reg_no = dict.get('jamb_reg_no',None)
746        if jamb_reg_no:
747            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
748            if res:
749                return '',"jamb_reg_no exists"
750        matric_no = dict.get('matric_no',None)
751        if matric_no:
752            res = self.students_catalog(matric_no = matric_no)
753            if res:
754                return '',"matric_no exists"
755        sid = self.waeup_tool.generateStudentId('?')
756        students_folder.invokeFactory('Student', sid)
757        student_obj = getattr(students_folder,sid)
758        f2t = self.student_field2types
759        d = {}
760        d['jamb_sex']  = 'M'
761        if dict.get('sex'):
762            d['jamb_sex']  = 'F'
763        for pt in f2t.keys():
764            student_obj.invokeFactory(pt,f2t[pt]['id'])
765            sub_obj = getattr(student_obj,f2t[pt]['id'])
766            sub_doc = sub_obj.getContent()
767            d['Title'] = f2t[pt]['title']
768            for field in f2t[pt]['fields']:
769                d[field] = dict.get(field,'')
770            sub_doc.edit(mapping = d)
771            new_state = f2t[pt]['wf_transition']
772            if new_state != "remain":
773                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
774        wfaction = 'return'
775        self.portal_workflow.doActionFor(student_obj,wfaction)
776        student_obj.manage_setLocalRoles(sid, ['Owner',])
777        return sid,''
778    ###)
779
780    security.declareProtected(ModifyPortalContent,'importEditStudent') ###(
781    def importEditStudent(self,dict):
782        "edit a students record due import"
783        logger = logging.getLogger('WAeUPTool.importEditStudent')
784        students_folder = self.portal_url.getPortalObject().campus.students
785        sid = dict.get('id',None)
786        jamb_reg_no = dict.get('jamb_reg_no',None)
787        matric_no = dict.get('matric_no',None)
788        if sid:
789            res = self.students_catalog(id = sid)
790            if not res:
791                return '',"no student with id %s" % sid
792            elif matric_no and res[0].matric_no and\
793              matric_no != res[0].matric_no:
794                return '%s' % res[0].id ,"student has no matric_no %s" % matric_no
795            elif jamb_reg_no and res[0].jamb_reg_no and\
796              jamb_reg_no != res[0].jamb_reg_no:
797                return '%s' % res[0].id ,"student has no jamb_reg_no %s" % jamb_reg_no
798        elif matric_no:
799            res = self.students_catalog(matric_no = matric_no)
800            if not res:
801                return '',"no student with matric_no %s" % matric_no
802            elif jamb_reg_no and res[0].jamb_reg_no and\
803              jamb_reg_no != res[0].jamb_reg_no:
804                return '%s' % res[0].id ,"student has no jamb_reg_no %s" % jamb_reg_no
805        elif jamb_reg_no:
806            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
807            if not res:
808                return '',"no student with jamb_reg_no %s" % jamb_reg_no
809        sid = res[0].id
810        student_obj = getattr(students_folder,sid)
811        f2t = self.student_field2types
812        d = {}
813        d['jamb_sex']  = 'M'
814        if dict.get('sex'):
815            d['jamb_sex']  = 'F'
816        for pt in f2t.keys():
817            sub_obj = getattr(student_obj,f2t[pt]['id'],None)
818            if sub_obj is None:
819                try:
820                    student_obj.invokeFactory(pt,f2t[pt]['id'])
821                except:
822                    continue
823                sub_obj = getattr(student_obj,f2t[pt]['id'])
824            sub_doc = sub_obj.getContent()
825            # self.portal_workflow.doActionFor(sub_obj,'open',dest_container=sub_obj)
826            d['Title'] = f2t[pt]['title']
827            for field in f2t[pt]['fields']:
828                d[field] = dict.get(field,'')
829            sub_doc.edit(mapping = d)
830            # new_state = f2t[pt]['wf_transition']
831            # if new_state != "remain":
832            #     self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
833        # wfaction = 'return'
834        # self.portal_workflow.doActionFor(student_obj,wfaction)
835        # student_obj.manage_setLocalRoles(sid, ['Owner',])
836        return sid,''
837    ###)
838
839    security.declareProtected(ModifyPortalContent,"importData")###(
840    def importData(self,filename,name,edit=False):
841        """load data from CSV values"""
842        import transaction
843        import random
844
845        pm = self.portal_membership
846        member = pm.getAuthenticatedMember()
847
848        logger = logging.getLogger('WAeUPTool.importData')
849        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
850        students_folder = self.portal_url.getPortalObject().campus.students
851        start = True
852        tr_count = 1
853        total_imported = 0
854        total_not_imported = 0
855        total = 0
856        iname = "import_%s" % name
857        stool = getToolByName(self, 'portal_schemas')
858        ltool = getToolByName(self, 'portal_layouts')
859        schema = stool._getOb(iname)
860        if schema is None:
861            em = 'No such schema %s' % iname
862            logger.error('No such schema %s' % iname)
863            return em
864        layout = ltool._getOb(iname)
865        if layout is None:
866            em = 'No such layout %s' % iname
867            logger.error(em)
868            return em
869        validators = {}
870        for widget in layout.keys():
871            validators[widget] = layout[widget].validate
872        if edit:
873            importer_name = "importEdit%s" % name.capitalize()
874        else:
875            importer_name = "import%s" % name.capitalize()
876        importer = getattr(self, '%s' % importer_name,None)
877        if importer is None:
878            em = 'No importer function %s' % importer_name
879            logger.error(em)
880            return em
881        not_imported = []
882        imported = []
883        try:
884            items = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
885        except:
886            em = 'Error reading %s.csv' % filename
887            logger.error(em)
888            return em
889        for item in items:
890            tr_count += 1
891            if start:
892                start = False
893                adapters = [MappingStorageAdapter(schema, item)]
894                dm = DataModel(item, adapters,context=self)
895                logger.info('%s starts import from %s.csv' % (member,filename))
896                import_keys = [k for k in item.keys() if not k.startswith('ignore')]
897                diff2schema = set(import_keys).difference(set(schema.keys()))
898                diff2layout = set(import_keys).difference(set(layout.keys()))
899                if diff2schema:
900                    em = "not ignorable key(s) %s found in heading" % diff2schema
901                    return em
902                s = ','.join(['"%s"' % fn for fn in import_keys])
903                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(s + ',"Error"'+ '\n')
904                s = '"id",' + s
905                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
906                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
907                format_error = format + ',"%(Error)s"'
908                format = '"%(id)s",'+ format
909            ds = DataStructure(data=item,datamodel=dm)
910            error_string = ""
911            for k in import_keys:
912                # if k == "birthday":
913                #     from pdb import set_trace; set_trace()
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.