source: WAeUP_SRP/trunk/WAeUPTool.py @ 1790

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

import fields changed

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