source: WAeUP_SRP/trunk/WAeUPTool.py @ 1778

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

create also payment object in importStudent
unused methods removed from Students.py

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