source: WAeUP_SRP/trunk/WAeUPTool.py @ 1784

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

email and phone was not copied into application and personal after first login

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