source: WAeUP_SRP/base/WAeUPTool.py @ 2675

Last change on this file since 2675 was 2675, checked in by joachim, 18 years ago

new images directory structure

  • Property svn:keywords set to Id
File size: 78.9 KB
RevLine 
[1991]1#-*- mode: python; mode: fold -*-
[197]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 2675 2007-11-16 09:45:30Z joachim $
[1174]20"""The WAeUP Tool Box.
[197]21"""
22
23from AccessControl import ClassSecurityInfo
[828]24from Acquisition import aq_inner
25from Acquisition import aq_parent
26from Globals import DTMLFile
27from Globals import InitializeClass
28from OFS.SimpleItem import SimpleItem
[2283]29from zExceptions import BadRequest
[197]30
[1890]31from Products.CMFCore.utils import getToolByName
[1747]32from Products.CPSSchemas.DataStructure import DataStructure
33from Products.CPSSchemas.DataModel import DataModel
34from Products.CPSSchemas.StorageAdapter import MappingStorageAdapter
[828]35from Products.CMFCore.ActionProviderBase import ActionProviderBase
36from Products.CMFCore.permissions import View
37from Products.ZCatalog.ZCatalog import ZCatalog
38from Products.CMFCore.permissions import ModifyPortalContent
[1890]39from Products.CMFCore.permissions import ManagePortal
[197]40from Products.CMFCore.utils import UniqueObject
[1194]41from Products.CMFCore.URLTool import URLTool
[1747]42from Products.CMFCore.utils import getToolByName
[1151]43from Students import makeCertificateCode
[1285]44from Globals import package_home,INSTANCE_HOME
[2094]45import DateTime,time
[1620]46import logging
[1170]47import transaction
[2193]48import csv,re,os,sys
[2413]49from shutil import copy2
[1707]50from Products.AdvancedQuery import Eq, Between, Le,In
[197]51
[2413]52p_home = package_home(globals())
53i_home = INSTANCE_HOME
54images_base = os.path.join(i_home,"images")
55
[2675]56def getImagesDir(student_id):
57    return os.path.join("%s" % images_base,student_id[0],student_id)
[2413]58
[1707]59def getObject(object,name):
60    if object.hasObject(name):
61        return getattr(object,name)
62    return None
[1720]63
[828]64class WAeUPTool(UniqueObject, SimpleItem, ActionProviderBase):
[197]65    """WAeUP tool"""
66
[828]67    id = 'waeup_tool'
[197]68    meta_type = 'WAeUP Tool'
[828]69    _actions = ()
[197]70    security = ClassSecurityInfo()
[828]71    security.declareObjectProtected(View)
72    manage_options = ( ActionProviderBase.manage_options
73                     + SimpleItem.manage_options
74                     )
75
[1818]76    def rwrite(self,s): ###(
[1707]77        response = self.REQUEST.RESPONSE
78        response.setHeader('Content-type','text/html; charset=ISO-8859-15')
79        response.write("%s<br />\r\n" % s)
[1818]80    ###)
[1174]81
[1818]82    def sleep(self,secs): ###(
83        "sleep"
84        import time
85        time.sleep(secs)
86        return
[1827]87
[1818]88###)
89
90    security.declareProtected(ModifyPortalContent,'openLog') ###(
[1716]91    def openLog(self,name):
92        """open a log file"""
93        version = 1
94        path = "%s/log/%s_%d.log" % (i_home,name,version)
95        while os.path.exists(path):
96            version += 1
97            path = "%s/log/%s_%d.log" % (i_home,name,version)
98        log = open(path,"w")
99        return log
[2259]100    ###)
[1716]101
[2259]102    security.declareProtected(ModifyPortalContent,'bypassQueueCatalog') ###(
103    def bypassQueueCatalog(self,enable=True):
104        """bypass the QueueCatalog by setting all indexes to process imediate,
105        if enable is True (default) the old settings are restored
106        """
[1818]107
[2259]108    ###)
109
[2094]110    security.declareProtected(ModifyPortalContent,'measureOaT') ###(
111    def measureOaT(self,method="a",probe="1000",nr_pts="1"):
112        """measure Object access Time"""
113        import random
114        if hasattr(self,'portal_catalog_real'):
115            aq_portal = self.portal_catalog_real.evalAdvancedQuery
116        else:
117            aq_portal = self.portal_catalog.evalAdvancedQuery
118        nr_pts = int(nr_pts)
119        probe = int(probe)
120        intervall = probe/10
121        objects = ("application","clearance","personal")
122        portal_types = ("StudentApplication","StudentClearance","StudentPersonal")
123        #i = random.randrange(num_objects)
124        count = 0
125        found = 0
126        not_found = 0
127        t_found = 0
128        t_not_found = 0
129        time_found = time_not_found = 0.0
130        t_time_found = t_time_not_found = 0.0
131        accessed = []
132        t_min = 1000
133        t_max = 0
134        #import pdb;pdb.set_trace()
135        students = self.portal_catalog(portal_type="Student")
136        num_students = len(students)
137        if method == "d":
138            query = Eq('path','/uniben/campus/students') & In('portal_type',portal_types[:nr_pts])
139            res = aq_portal(query)
140            brains = {}
141            for r in res:
142                sid = r.relative_path.split('/')[-2]
143                if brains.has_key(sid):
144                    brains[sid][r.portal_type] = r
145                else:
146                    brains[sid] = {r.portal_type : r}
147            brains_list = brains.keys()
148            num_objects = len(brains_list)
149        else:
150            num_objects = num_students
151        print "="*40
152        print "method: %s probes: %d nr_pts: %d num_objects: %d" % (method,
153                                                                        probe,
154                                                                        nr_pts,
155                                                                        num_objects)
156        print "nr found/not time found/not min/max"
157        elapse = time.time()
158        i_elapse = time.time()
159        c_elapse = time.clock()
160        for c in range(1,probe + 1):
161            i = random.randrange(num_objects)
162            if method in ('a','b','c'):
163                student_brain = students[i]
164            elif method == "d":
165                #import pdb;pdb.set_trace()
166                student_brain = brains[brains_list[i]]
167            if method == "c":
168                query = Eq('path',student_brain.getPath()) & In('portal_type',portal_types[:nr_pts])
169                res = aq_portal(query)
170                this_portal_types = [r.portal_type for r in res]
171            for i in range(nr_pts):
172                oid = objects[i]
173                if method == "a":
174                    try:
175                        student_path = student_brain.getPath()
176                        path = "%s/%s" % (student_path,oid)
177                        doc = self.unrestrictedTraverse(path).getContent()
178                        found += 1
179                        i_time = time.time() - i_elapse
180                        time_found += i_time
181                    except:
182                        not_found += 1
183                        i_time = time.time() - i_elapse
184                        time_not_found += i_time
185                        pass
186                elif method == "b":
187                    try:
188                        student_object = student_brain.getObject()
189                        doc = getattr(student_object,oid).getContent()
190                        found += 1
191                        i_time = time.time() - i_elapse
192                        time_found += i_time
193                    except:
194                        i_time = time.time() - i_elapse
195                        time_not_found += i_time
196                        not_found += 1
197                        pass
198                elif method == "c":
199                    if portal_types[i] in this_portal_types:
200                        found += 1
201                        doc = res[this_portal_types.index(portal_types[i])].getObject().getContent()
202                        i_time = time.time() - i_elapse
203                        time_found += i_time
204                    else:
205                        not_found += 1
206                        i_time = time.time() - i_elapse
207                        time_not_found += i_time
208                elif method == "d":
209                    if student_brain.has_key(portal_types[i]):
210                        found += 1
211                        doc = student_brain[portal_types[i]].getObject().getContent()
212                        i_time = time.time() - i_elapse
213                        time_found += i_time
214                    else:
215                        not_found += 1
216                        i_time = time.time() - i_elapse
217                        time_not_found += i_time
218                i_elapse = time.time()
219            if c and (c % intervall == 0):
220                #i_time = time.time() - i_elapse
221                t_per = 0.0
222                if found:
223                    t_per = time_found/found
224                if t_per > t_max:
225                    t_max = t_per
226                if t_per > 0.0 and t_per < t_min:
[2119]227                    t_min = t_per
[2094]228                itf = 0.0
229                if found:
230                    itf = time_found/found
231                itnf = 0.0
232                if not_found :
233                    itnf = time_not_found / not_found
[2119]234                interval_time = time_found + time_not_found
235                s = "%(c)d: %(found)d/%(not_found)d " % vars()
[2094]236                s += "%(interval_time)6.2f %(itf)6.4f/%(itnf)6.4f " % vars()
237                s += "%(t_min)6.4f/%(t_max)6.4f" %  vars()
238                print s
239                t_found += found
240                t_not_found += not_found
241                t_time_found += time_found
242                t_time_not_found += time_not_found
243                time_found = time_not_found = 0.0
244                found = not_found = 0
245        # t_found += found
246        # t_not_found += not_found
247        elapse = time.time() - elapse
248        itf = 0.0
249        if t_found:
250            itf = t_time_found/t_found
251        itnf = 0.0
252        if t_not_found:
253            itnf = t_time_not_found / t_not_found
254        #c_elapse = time.clock() - c_elapse
[2119]255        s = "%(probe)d: %(t_found)d/%(t_not_found)d " % vars()
[2094]256        s += "%(elapse)6.2f %(itf)6.4f/%(itnf)6.4f " % vars()
257        s += "%(t_min)6.4f/%(t_max)6.4f" %  vars()
258        print "-"*40
259        print s
260        rel_found = float(t_found)/probe
261        rel_not_found = float(t_not_found)/probe
262        estimated_total_time = num_objects*(rel_found*itf + rel_not_found*itnf)
263        print estimated_total_time
264    ###)
265
[1818]266    security.declareProtected(ModifyPortalContent,'writeLog') ###(
[1716]267    def writeLog(self,logfile,s):
268        """write to the log file"""
269        logfile.write(s)
270
[1818]271###)
[1720]272
[1151]273    def generateStudentId(self,letter): ###(
274        import random
275        r = random
[1194]276        ##if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
277        if letter == '?':
[1151]278            letter= r.choice('ABCDEFGHKLMNPQRSTUVWXY')
279        sid = "%c%d" % (letter,r.randint(99999,1000000))
[1720]280        students = self.portal_url.getPortalObject().campus.students
[1721]281##        while hasattr(students, sid):
282##            sid = "%c%d" % (letter,r.randint(99999,1000000))
283        while self.students_catalog(id = sid):
[1720]284            sid = "%c%d" % (letter,r.randint(99999,1000000))
[1151]285        return sid
[1460]286    ###)
[1415]287
288    def generatePassword(self,s=None): ###(
289        import random
290        r = random
291        ##if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
292        if s is None:
293            s = 'abcdefghklmnpqrstuvwxy23456789'
294        pw = ''
295        while len(pw) < 6:
296            pw += r.choice(s)
297        return pw
[1151]298    ###)
[828]299
[2645]300    security.declareProtected(ModifyPortalContent, 'dumpSchoolfeePayments') ###(
301    def dumpSchoolfeePayments(self):
302        "dump paid schoolfees"
[2666]303        mtool = self.portal_membership
304        member = mtool.getAuthenticatedMember()
[2645]305        logger = logging.getLogger('WAeUPTool.dumpSchoolfees')
306        aq_student = self.students_catalog.evalAdvancedQuery
307        query = In('review_state',('schoolfee_paid',
308                                   'courses_registered',
309                                   'courses_validated',
310                                   ))
311        res = aq_student(query)
[2666]312        #import pdb;pdb.set_trace()
[2645]313        l = []
314        logger.info("start for %d" % len(res))
315        count = 1
316        log_after = 100
317        for student in res:
[2656]318            if not count % log_after:
[2645]319                logger.info("processed %d total %d" % (log_after,count))
320            count += 1
321            fee_dict =self.getSchoolFee(student)
322            fulltime = student.mode.endswith('_ft')
323            d = {}
324            d['student_id'] = student.id
[2666]325            d['name'] = student.name
326            d['amount'] = fee_dict.get(new_returning)
[2645]327            l += d,
[2666]328        csv_name = self.dumpListToCSV(l,'payments')
329        logger.info('%s dumped payments to %s' % (member,export_file))
[2645]330    ###)
331
[2666]332    security.declarePublic('dumpListToCSV') ###(
333    def dumpListToCSV(self,l,filename,fields=None):
334        """dump a list of dicts to a CSV file"""
335        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
336        export_file = "%s/export/%s_%s.csv" % (i_home,filename,current,)
337        if fields is None:
338            fields = l[0].keys()
339        headline = ','.join(fields)
340        out = open(export_file,"wb")
341        out.write(headline +'\n')
342        out.close()
343        out = open(export_file,"a")
344        csv_writer = csv.DictWriter(out,fields,)
345        csv_writer.writerows(l)
346        return export_file
347    ###)
348
[2643]349    security.declareProtected(ManagePortal, 'listMembers') ###(
350    def listMembers(self):
351        "list all members"
352        mtool = self.portal_membership
353        member = mtool.getAuthenticatedMember()
354        logger = logging.getLogger('WAeUPTool.listMembers')
355        if str(member) not in ('admin','joachim'):
356            logger.info('%s tried to list members' % (member))
357            return None
358        members = self.portal_directories.members
359        all = members.listEntryIdsAndTitles()
360        l = []
361        for user_id,name in all:
362            d = {}
363            d['user_id'] = user_id
364            d['name'] = name
365            d['pw'] = getattr(getattr(members,user_id),'password')
[2645]366            d['email'] = getattr(getattr(members,user_id),'email')
367            d['groups'] = " ".join(getattr(getattr(members,user_id),'groups'))
368            d['roles'] = " ".join(getattr(getattr(members,user_id),'roles'))
[2643]369            l += d,
370        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
371        export_file = "%s/export/member_list_%s.csv" % (i_home,current,)
372        logger.info('%s dumped memberlist to %s' % (member,export_file))
373        fields = l[0].keys()
374        headline = ','.join(fields)
375        out = open(export_file,"wb")
376        out.write(headline +'\n')
377        out.close()
378        out = open(export_file,"a")
379        csv_writer = csv.DictWriter(out,fields,)
380        csv_writer.writerows(l)
381    ###)
[2656]382
[1890]383    security.declareProtected(ManagePortal, 'removeDeletedDocIds') ###(
384    def removeDeletedDocIds(self, max=1000):
385        """
386        remove deleted docids from repository commit after max
387        """
388        logger = logging.getLogger('WAeUPTool.removeDeletedDocIds')
389        repository = getToolByName(self, 'portal_repository')
390        pxtool = getToolByName(self, 'portal_proxies')
[2632]391        logger.info('start')
[1890]392        pxtool_infos = pxtool.getRevisionsUsed()
[2632]393        logger.info('found  %d used revisions ' % (len(pxtool_infos)))
[1895]394
[1890]395        nb_revs = 0
396        docids_d = {} # all docids
397        unused_docids_d = {} # all docids that are unused
398        ids_unused_revs_docids = [] # ids for revs of unused docids
[2632]399        unused_ids = [] # ids for unused revs
[1890]400        total = 0
[1895]401        idlist = repository.objectIds()
[2632]402        to_delete = 0
403        found = False
[1895]404        for id in idlist:
[1890]405            docid, rev = repository._splitId(id)
406            if docid is None:
407                logger.info("invalid doc_id %s" % docid)
408                continue
409            nb_revs += 1
410            if not pxtool_infos.has_key(docid):
[2632]411                found = True
412                to_delete += 1
413                unused_ids.append(id)
[1890]414            elif not pxtool_infos[docid].has_key(rev):
[2632]415                found = True
416                to_delete += 1
417                unused_ids.append(id)
418            if found and not to_delete % max:
419                found = False
[1890]420                #import pdb;pdb.set_trace()
[2632]421                repository.manage_delObjects(unused_ids)
[1890]422                transaction.commit()
[2632]423                logger.info('removed %d total %d unused docids ' % (max,to_delete))
424        else:
425            if unused_ids:
426                repository.manage_delObjects(unused_ids)
427                transaction.commit()
428        logger.info('finished removing %d unused docids ' % (to_delete))
[1890]429
[1895]430
[1890]431###)
432
[2562]433    security.declareProtected(View,'getCredential') ###(
[1250]434    def getCredential(self,student_id):
435        "return a student password"
436        student_entry = getattr(self.portal_directories.students,student_id,None)
[2555]437        if not self.isStaff():
[2563]438            mtool = self.portal_membership
439            member = mtool.getAuthenticatedMember()
440            logger = logging.getLogger('WAeUPTool.getCredential')
441            logger.info('%s tried to access password of %s' % (member,student_id))
[2555]442            return None
[1250]443        if student_entry is None:
444            return None
[1263]445        return getattr(student_entry,"password","not set")
[1261]446    ###)
[1250]447
[1460]448    security.declarePublic('checkPassword') ###(
[1467]449    def checkPassword(self,student_id,password):
[1460]450        "return a student password"
451        student_entry = getattr(self.portal_directories.students,student_id,None)
452        if student_entry is None:
453            return False
454        return getattr(student_entry,"password","not set") == password
455    ###)
456
[2556]457    security.declareProtected(ModifyPortalContent,'editPassword') ###(
[1467]458    def editPassword(self,student_id,password):
459        "edit a student password"
460        student_entry = getattr(self.portal_directories.students,student_id,None)
461        if student_entry is None:
[1571]462            return
[1467]463        setattr(student_entry,'password',password)
464    ###)
465
[2555]466    security.declareProtected(ModifyPortalContent,'doCommit') ###(
[1401]467    def doCommit(self,logger=None):
468        "commit some transactions"
469        transaction.commit()
470    ###)
471
[2675]472
[1285]473    security.declarePublic('loadStudentFoto') ###(
[1813]474    def loadStudentFoto(self,student,filename,folder):
[1285]475        "return a student passport picture"
[2413]476        #import pdb;pdb.set_trace()
477        picture ="%s/import/%s/%s" % (i_home,folder,filename)
478        student_id = student.getId()
[2675]479        images_dir = getImagesDir(student_id)
[2413]480        if not os.path.exists(images_dir):
481            os.mkdir(images_dir)
482        image_name = os.path.join(images_dir,"passport_%(student_id)s.jpg" % vars())
483        for extension in ('.jpg','.JPG'):
484            fullname = "%(picture)s%(extension)s" % vars()
485            if os.path.exists(fullname):
486                copy2(fullname,image_name)
487                return "successfully copied passport picture"
[2467]488        return "passport picture not found: %s.jpg or .JPG" % picture
[2413]489    ###)
490
[2420]491    def old____loadStudentFoto(self,student,filename,folder): ###(
[2413]492        "return a student passport picture"
[1921]493        app = student.application
494        app_doc = app.getContent()
[1813]495        #clear = student.clearance
496        #clear_doc = clear.getContent()
497        #matric_no = clear_doc.matric_no.upper()
498        picture1 ="%s/import/%s/%s.jpg" % (i_home,folder,filename)
499        picture2 ="%s/import/%s/%s.JPG" % (i_home,folder,filename)
[1285]500        #import pdb;pdb.set_trace()
[1286]501        if os.path.exists(picture1):
502            file = open(picture1)
503        elif os.path.exists(picture2):
[1287]504            file = open(picture2)
[1286]505        else:
[1287]506            return "passport picture not found %s" % picture1
[1921]507        reopened = False
508        if self.portal_workflow.getInfoFor(app,'review_state',None) !='opened':
509            self.portal_workflow.doActionFor(app,'open')
510            reopened = True
[1285]511        outfile = file.read()
512        app_doc.manage_addFile('passport',
513                               file=outfile,
[1818]514                               title="%s.jpg" % filename)
[1921]515        if reopened:
516            self.portal_workflow.doActionFor(app,'close')
[1286]517        return "successfully loaded passport picture"
[1285]518    ###)
519
[1170]520    security.declareProtected(ModifyPortalContent,'createOne') ###(
[1194]521    def createOne(self,students_folder,student_brain,letter,commit=False):
522        sid = self.waeup_tool.generateStudentId(letter)
[1170]523        students_folder.invokeFactory('Student', sid)
524        student = getattr(students_folder,sid)
525        self.portal_workflow.doActionFor(student,'return')
526        student.manage_setLocalRoles(sid, ['Owner',])
527        matric_no = student_brain.matric_no
528        jamb_reg_no = student_brain.Entryregno
529        self.students_catalog.addRecord(id = sid,
530                                           matric_no = matric_no,
531                                           jamb_reg_no = jamb_reg_no,
532                                           sex = student_brain.Sex == "F",
533                                           name = "%s %s %s" % (student_brain.Firstname,
534                                                                student_brain.Middlename,
535                                                                student_brain.Lastname)
536                                        )
537        if commit:
538            transaction.commit()
539        return sid,jamb_reg_no
540    ###)
541
[1752]542    security.declareProtected(ModifyPortalContent,'addStudent') ###(
543    def addStudent(self,dict):
[1415]544        students_folder = self.portal_url.getPortalObject().campus.students
545        sid = self.waeup_tool.generateStudentId('?')
546        students_folder.invokeFactory('Student', sid)
547        student_obj = getattr(students_folder,sid)
[1728]548        f2t = self.student_field2types
[1772]549        #from pdb import set_trace; set_trace()
550        d = {}
[2297]551        #d['jamb_sex']  = 'M'
552        #if dict.get('sex'):
553        #    d['jamb_sex']  = 'F'
[1904]554
[1898]555        entry_session = dict.get('entry_session')
[2454]556        if entry_session == self.getSessionId()[0]:
[1898]557            wfaction = 'admit'
[1991]558            wft = 'wf_transition_admit'
[1900]559            password = None
[1904]560        else:
[1900]561            wfaction = 'return'
[1991]562            wft = 'wf_transition_return'
[1900]563            password = self.generatePassword()
[1904]564            self.makeStudentMember(sid,password)
565
[1728]566        for pt in f2t.keys():
567            student_obj.invokeFactory(pt,f2t[pt]['id'])
568            sub_obj = getattr(student_obj,f2t[pt]['id'])
569            sub_doc = sub_obj.getContent()
[1898]570            #self.portal_workflow.doActionFor(sub_obj,'open',dest_container=sub_obj)
[1772]571            d['Title'] = f2t[pt]['title']
[1728]572            for field in f2t[pt]['fields']:
[1749]573                d[field] = dict.get(field,'')
[1728]574            sub_doc.edit(mapping = d)
[1898]575            new_state = f2t[pt][wft]
[1772]576            if new_state != "remain":
577                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
[1415]578        self.portal_workflow.doActionFor(student_obj,wfaction)
579        student_obj.manage_setLocalRoles(sid, ['Owner',])
580        return sid,password
581    ###)
582
[1151]583    security.declarePublic('getCertificateBrain') ###(
584    def getCertificateBrain(self,cert_id):
585        "do it"
[1849]586        res = ZCatalog.searchResults(self.portal_catalog_real,
[1151]587                                {'portal_type':"Certificate",
588                                      'id': cert_id})
589        if res:
590            return res[0]
591        return None
592    ###)
[1160]593
[1756]594    security.declareProtected(ModifyPortalContent,'get_csv_filenames') ###(
595    def get_csv_filenames(self):
596        "do it"
[1759]597        files = [file for file in os.listdir("%s/import/" % (i_home))
[1756]598                 if file.endswith('.csv') and file.find('imported') == -1]
599        return files
600    ###)
601
[1151]602    security.declarePublic('findStudentByMatricelNo') ###(
603    def findStudentByMatricelNo(self,matric_no):
604        "do it"
[1849]605        res = ZCatalog.searchResults(self.portal_catalog_real,
[1151]606                                {'portal_type':"StudentClearance",
607                                 'SearchableText': matric_no})
608        if res:
609            return res[0]
610        return None
611    ###)
612
[2557]613    security.declarePublic('makeStudentMember') ###(
[1151]614    def makeStudentMember(self,sid,password='uNsEt'):
615        """make the student a member"""
616        membership = self.portal_membership
617        membership.addMember(sid,
618                             password ,
619                             roles=('Member',
620                                     'Student',
621                                     ),
622                             domains='',
623                             properties = {'memberareaCreationFlag': False,
624                                           'homeless': True},)
625        member = membership.getMemberById(sid)
626        self.portal_registration.afterAdd(member, sid, password, None)
[1261]627        #self.manage_setLocalRoles(sid, ['Owner',])
[1151]628    ###)
[1160]629
[2560]630    security.declareProtected(View,'makeStudentData') ###(
[1158]631    def makeStudentData(self,student_id,email=None,phone_nr=None):
[1151]632        "create Datastructure for a returning Student"
[1406]633        #import pdb;pdb.set_trace()
[1571]634        logger = logging.getLogger('WAeUPTool.makeStudentData')
[1151]635        students_folder = self.portal_url.getPortalObject().campus.students
[1794]636        #res = self.students_catalog(id=student_id)
637        #if res:
638        #    st = res[0]
639        #res = self.returning_import(matric_no = st.matric_no)
[1798]640        res = self.returning_import(id = student_id)
[1151]641        if res:
[1160]642            student = res[0]
[1794]643        else:
[1816]644            logger.info('Id %s not found in returning_import' % student_id)
[1794]645            return
[1580]646        logger.info('%s creates data structure' % student_id)
[1794]647        s_results = self.results_import(matric_no = student.matric_no)
[1816]648        if s_results:
649            lnr = self.getLevelFromResultsCosCode(s_results)
650            level = "%d00" % lnr
651            verdict,eligible = self.getVerdict(s_results[0].Verdict)
[2454]652            #if eligible:
653            #    level = "%d00" % (lnr + 1)
[1816]654        else:
655            logger.info('matric_no %s not found in results_import' % student.matric_no)
[2656]656            level = ''
657            verdict = ''
[1171]658        #student should not be allowed to perform this transition
[1174]659        #wftool = self.portal_workflow
660        #wftool.doActionFor(student,'return')
[1151]661        certcode_org = student.Coursemajorcode
662        certcode = makeCertificateCode(certcode_org)
663        certificate_brain = self.getCertificateBrain(certcode)
664        if not certificate_brain:
665            em = 'Certificate %s org-code %s not found\n' % (certcode, certcode_org)
666            logger.info(em)
667        matric_no = student.matric_no
668        sid = student_id
669        student_obj = getattr(students_folder,sid)
670        student_obj.invokeFactory('StudentApplication','application')
671        application = student_obj.application
[1169]672        self.portal_workflow.doActionFor(application,'open',dest_container=application)
[1151]673        da = {'Title': 'Application Data'}
674        student_obj.invokeFactory('StudentPersonal','personal')
675        da['jamb_reg_no'] = student.Entryregno
[1462]676        em = self.getEntryMode(student.Entryregno)
[1401]677        da['entry_mode'] = em
[1151]678        personal = student_obj.personal
679        self.portal_workflow.doActionFor(personal,'open',dest_container=personal)
680        dp = {'Title': 'Personal Data'}
681        student_obj.invokeFactory('StudentClearance','clearance')
682        clearance = student_obj.clearance
[1169]683        self.portal_workflow.doActionFor(clearance,'open',dest_container=clearance)
[1151]684        dc = {'Title': 'Clearance/Eligibility Record'}
685        dc['matric_no'] = matric_no
686        state = student.State
687        lga = student.LGA
688        if state and lga:
689            lga =  state + ' / ' + lga
690        else:
691            lga = "None"
[1174]692        da['jamb_lga'] = dc['lga'] = lga
[1173]693        da['app_email'] = dp['email'] = email
694        da['app_mobile'] = dp['phone'] = phone_nr
[1411]695        dp['firstname'] = student.Firstname
696        dp['middlename'] = student.Middlename
697        dp['lastname'] = student.Lastname
698        da['jamb_lastname'] = "%s %s %s" % (student.Firstname,student.Middlename,student.Lastname)
[1174]699        da['jamb_sex'] = student.Sex
[1151]700        dp['sex'] = student.Sex == 'F'
701        dp['perm_address'] = student.Permanent_Address
702        application.getContent().edit(mapping=da)
[1169]703        self.portal_workflow.doActionFor(application,'close',dest_container=application)
[1151]704        personal.getContent().edit(mapping=dp)
705        clearance.getContent().edit(mapping=dc)
[1169]706        self.portal_workflow.doActionFor(clearance,'close',dest_container=clearance)
[1151]707        #
708        # Study Course
709        #
710        student_obj.invokeFactory('StudentStudyCourse','study_course')
711        studycourse = student_obj.study_course
712        self.portal_workflow.doActionFor(studycourse,'open',dest_container=studycourse)
713        dsc = {}
714        dsc['study_course'] = certcode
[1401]715        dsc['current_level'] = level
716        dsc['current_verdict'] = verdict
[1827]717        dsc['current_mode'] = em
[2466]718        dsc['current_session'] = '05'
[1151]719        studycourse.getContent().edit(mapping=dsc)
720        #
721        # Level
722        #
[1198]723##        l = getattr(studycourse,level,None)
724##        if l is None:
725##            studycourse.invokeFactory('StudentStudyLevel', level)
726##            l = getattr(studycourse, level)
727##            self.portal_workflow.doActionFor(l,'open',dest_container=l)
728##            l.getContent().edit(mapping={'Title': "Level %s" % level})
[1194]729###)
[1160]730
[2556]731    security.declareProtected(ModifyPortalContent,'admitOneStudent') ###(
[2576]732    def admitOneStudent(self,brain,entry_session,pin_password):
[2514]733        "create Datastructure for an admitted Student"
734        #import pdb;pdb.set_trace()
735        students_folder = self.portal_url.getPortalObject().campus.students
736        logger = logging.getLogger('WAeUPTool.admitStudent')
737        if brain.status != "admitted":
738            logger.info('status of %s is %s' % (brain.reg_no,brain.status))
[2540]739            return
[2514]740        pin_parts = brain.pin.split('-')
741        if len(pin_parts) != 3:
742            logger.info('invalid pin %s for %s' % (brain.pin,brain.reg_no))
[2540]743            return
744        student_id = self.generateStudentId('?')
[2514]745        students_folder.invokeFactory('Student', student_id)
746        student_object = getattr(students_folder,student_id)
[2576]747        if pin_password:
748            password = pin_parts[2]
749            self.makeStudentMember(student_id,password = password)
[2540]750        student_object.manage_setLocalRoles(student_id, ['Owner',])
751        #logger.info("creating %s reg_no %s" % (student_id,brain.reg_no))
[2514]752        #
753        # application
754        #
[2540]755        student_object.invokeFactory('StudentApplication','application')
756        application = student_object.application
[2575]757        #self.portal_workflow.doActionFor(application,'open',dest_container=application)
[2514]758        da = {'Title': 'Application Data'}
759        da['jamb_reg_no'] = brain.reg_no
[2576]760
[2540]761        sex = 'M'
762        if brain.sex:
763            sex = 'F'
764        da['jamb_sex'] = sex
[2670]765        da['jamb_age'] = brain.jamb_age
[2575]766        #da['app_ac_pin'] = brain.pin
[2670]767        da['jamb_lga'] = brain.jamb_lga
768        da['jamb_state'] = brain.jamb_state
[2575]769        da['jamb_score'] = brain.aggregate
[2514]770        da['app_email'] = brain.email
[2540]771        da['app_mobile'] = brain.phone
[2575]772        if brain.entry_mode:
773            da['entry_mode'] = brain.entry_mode
774        elif brain.screening_type == 'pume':
775            da['entry_mode'] = 'ume_ft'
776        elif brain.screening_type == 'pde':
777            da['entry_mode'] = 'de_ft'
778        else:
779            da['entry_mode'] = brain.screening_type
780        da['entry_session'] = entry_session
781        da['jamb_lastname'] = brain.lastname
782        da['jamb_middlename'] = brain.middlenames   # different field names!
[2670]783        da['jamb_firstname'] = brain.firstname
[2575]784        da['screening_application_date'] = brain.application_date
785        da['date_of_birth'] = brain.date_of_birth
786        da['jamb_first_cos'] = brain.course1
787        da['jamb_second_cos'] = brain.course2
788        da['course3'] = brain.course3
789        da['screening_type'] = brain.screening_type
790        da['screening_score'] = brain.screening_score
791        da['screening_date'] = brain.screening_date
792        da['hq_type'] = brain.hq_type
793        da['hq_grade'] = brain.hq_grade
794        da['aos'] = brain.aos
[2576]795
[2514]796        application.getContent().edit(mapping=da)
[2575]797        #self.portal_workflow.doActionFor(application,'close',dest_container=application)
[2514]798        #
799        # personal
800        #
[2540]801        student_object.invokeFactory('StudentPersonal','personal')
802        personal = student_object.personal
[2575]803        #self.portal_workflow.doActionFor(personal,'open',dest_container=personal)
[2514]804        dp = {'Title': 'Personal Data'}
805        dp['sex'] = brain.sex
806        dp['email'] = brain.email
[2540]807        dp['phone'] = brain.phone
[2514]808        dp['lastname'] = brain.lastname
[2575]809        dp['middlename'] = brain.middlenames   # different field names!
[2576]810        dp['firstname'] = brain.firstname
[2514]811        personal.getContent().edit(mapping=dp)
812        #
813        # clearance
814        #
[2540]815        student_object.invokeFactory('StudentClearance','clearance')
816        clearance = student_object.clearance
[2575]817        #self.portal_workflow.doActionFor(clearance,'open',dest_container=clearance)
[2514]818        dc = {'Title': 'Clearance/Eligibility Record'}
819        dc['lga'] = brain.lga
[2670]820        dc['birthday'] = brain.date_of_birth
[2514]821        clearance.getContent().edit(mapping=dc)
[2575]822        #self.portal_workflow.doActionFor(clearance,'close',dest_container=clearance)
[2514]823        #
824        # study Course
825        #
[2540]826        student_object.invokeFactory('StudentStudyCourse','study_course')
827        studycourse = student_object.study_course
[2575]828        #self.portal_workflow.doActionFor(studycourse,'open',dest_container=studycourse)
[2514]829        dsc = {}
830        dsc['study_course'] = brain.course_admitted
831        dsc['current_verdict'] = ''
[2575]832        dsc['current_mode'] = da['entry_mode']
833        if da['entry_mode'].startswith('de'):
834            dsc['current_level'] = '200'
835        else:
836            dsc['current_level'] = '100'
837        dsc['current_session'] = entry_session
[2514]838        studycourse.getContent().edit(mapping=dsc)
839        #
840        # payments folder
[2540]841        student_object.invokeFactory('PaymentsFolder','payments')
842        payments = getattr(student_object,'payments')
[2514]843        dpay = {}
844        dpay['Title'] = 'Payments'
845        payments.getContent().edit(mapping=dpay)
[2540]846        self.portal_workflow.doActionFor(payments,'open')
[2580]847        #
848        # passport foto
849        app_picture ="%s/import/images/%s/%s_passport.jpg" % (i_home,
850                                                              brain.screening_type,
851                                                              brain.reg_no)
[2675]852        images_dir = getImagesDir(student_id)
853        #images_dir = os.path.join("%s" % images_base,student_id)
854        letter_dir,student_dir = os.path.split(images_dir)
855        if not os.path.exists(letter_dir):
856            os.mkdir(letter_dir)
[2580]857        if not os.path.exists(images_dir):
858            os.mkdir(images_dir)
859        image_name = os.path.join(images_dir,"passport_%(student_id)s.jpg" % vars())
860        if os.path.exists(app_picture):
861            copy2(app_picture,image_name)
862        else:
863            logger.info('passport of %s/%s not found: %s' % (student_id,
864                                                             brain.reg_no,
865                                                             app_picture))
[2656]866
[2514]867        return student_id
868    ###)
869
[2556]870    security.declareProtected(ModifyPortalContent,'makeStudentLevel') ###(
[1194]871    def makeStudentLevel(self,student_id):
872        "create the StudyLevel for a returning Student"
873        #import pdb;pdb.set_trace()
[1571]874        logger = logging.getLogger('WAeUPTool.makeStudentLevel')
[1194]875        students_folder = self.portal_url.getPortalObject().campus.students
876        res = self.students_catalog(id=student_id)
877        if res:
878            st = res[0]
879        course = st.course
880        matric_no = st.matric_no
881        level = st.level
882        res = self.results_import(matric_no = matric_no)
883        if res:
884            results = res
[1571]885        logger.info('%s creating Level %s' % (student_id,level))
[1194]886        #
887        # Level
888        #
889        student_obj = getattr(self.portal_url.getPortalObject().campus.students,student_id)
890        studycourse = getattr(student_obj,"study_course",None)
891        self.portal_workflow.doActionFor(studycourse,'close_for_edit',dest_container=studycourse)
892        l = getattr(studycourse,level,None)
893        if l is None:
894            studycourse.invokeFactory('StudentStudyLevel', level)
895            l = getattr(studycourse, level)
896            self.portal_workflow.doActionFor(l,'open',dest_container=l)
897            l.getContent().edit(mapping={'Title': "Level %s" % level})
898        ###)
899
[2000]900    security.declarePublic('getHallInfo') ###(
901    def getHallInfo(self,bed):
902        """return Hall Info"""
[828]903        info = {}
904        hall,block,room,letter = bed.split('_')
[1846]905        res = ZCatalog.searchResults(self.portal_catalog_real,portal_type="AccoHall",id=hall)
[828]906        if res and len(res) == 1:
907            hall_brain = res[0]
908            hall_doc = hall_brain.getObject().getContent()
909        else:
910            return info
911        info['hall_title'] = hall_brain.Title
912        info['maintenance_code'] = hall_doc.maintenance_code
[1846]913        res = ZCatalog.searchResults(self.portal_catalog_real,portal_type="ScratchCardBatch")
[828]914        batch_doc = None
915        for brain in res:
916            if brain.id.startswith(info['maintenance_code']):
917                batch_doc = brain.getObject().getContent()
918                break
919        if batch_doc is None:
920            info['maintenance_fee'] = None
921        else:
922            info['maintenance_fee'] = batch_doc.cost
923        return info
[1151]924    ###)
[828]925
[2396]926    security.declareProtected(ModifyPortalContent,'removePictureFolder') ###(
927    def removePictureFolder(self,student_id):
928        """remove picture_folder by renaming it"""
929        path = 'images'
930        picture_path = os.path.join(i_home,path,student_id)
931        if not os.path.exists(picture_path):
932            return False
933        os.rename(picture_path,picture_path + "_removed")
934        return True
935    ###)
936
937    security.declareProtected(ModifyPortalContent,'restorePictureFolder') ###(
938    def restorePictureFolder(self,student_id):
939        """restore picture_folder by renaming it"""
940        path = 'images'
941        picture_path = os.path.join(i_home,path,student_id)
942        if not os.path.exists(picture_path + "_removed"):
943            return False
944        os.rename(picture_path + "_removed",picture_path)
945        return True
946    ###)
947
[2363]948    security.declarePublic('picturesExist') ###(
[2420]949    def picturesExist(self, ids,student_id=None):
[2363]950        """check if pictures exist in the filesystem"""
[2420]951        if student_id is None:
952            student_id = self.getStudentId()
953        if student_id is None:
954            return False
[2675]955        picture_path = getImagesDir(student_id)
956        #picture_path = os.path.join(images_base,student_id)
[2363]957        if not os.path.exists(picture_path):
958            return False
959        pictures  = [picture[:picture.rfind('_')] for picture in os.listdir(picture_path)]
960        return set(ids).issubset(set(pictures))
961    ###)
962
[2364]963    security.declarePublic('picturesList') ###(
964    def picturesList(self):
965        """check if pictures exist in the filesystem"""
966        path = 'images'
967        student_id = self.getStudentId()
968        picture_path = os.path.join(i_home,path,student_id)
969        if not os.path.exists(picture_path):
970            return []
971        return [picture[:picture.rfind('_')] for picture in os.listdir(picture_path)]
972    ###)
973
[2114]974    security.declarePublic('showFsPicture') ###(
975    def showFsPicture(self,path):
976        """return a picture from the filesystem"""
[2675]977        #picture_path = os.path.join(i_home,path)
978        picture_path = os.path.join(images_base,path)
[2335]979        response = self.REQUEST.RESPONSE
[2342]980        #import pdb;pdb.set_trace()
[2354]981        registry = getToolByName(self, 'mimetypes_registry')
982        mimetype = str(registry.lookupExtension(path.lower()) or
983                    registry.lookupExtension('file.bin'))
[2114]984        if os.path.exists(picture_path):
[2354]985            response.setHeader('Content-type',mimetype)
[2114]986            return open(picture_path).read()
[2335]987        picture_path = os.path.join(i_home,'import',path)
988        if os.path.exists(picture_path):
989            return open(picture_path).read()
[2114]990    ###)
991
[1151]992    security.declareProtected(ModifyPortalContent,'deleteAllCourses') ###(
993    def deleteAllCourses(self,department="All"):
994        ''' delete the courses'''
995        pm = self.portal_membership
996        member = pm.getAuthenticatedMember()
[1160]997
[1151]998        if str(member) not in ("henrik","joachim"):
999            return "not possible"
1000        if department == "All":
1001            res = self.portal_catalog({'meta_type': 'Department'})
1002        if len(res) < 1:
1003            return "No Departments found"
[1160]1004
[1151]1005        deleted = []
1006        for dep in res:
1007            cf = dep.getObject().courses
1008            if cf:
1009                cf.manage_delObjects(ids=cf.objectIds())
1010                deleted.append("deleted Courses in %s" % dep.getId)
1011        return "\r".join(deleted)
[1160]1012    ###)
[1151]1013
[1572]1014    security.declareProtected(ModifyPortalContent,'getLogfileLines') ###(
1015    def getLogfileLines(self,filename="event.log",numlines=20):
1016        """Get last NUMLINES lines of logfile FILENAME.
[1160]1017
[1572]1018        Return last lines' of a file in the instances logfile directory as
1019        a list. The number of returned lines equals `numlines' or less. If
1020        less than `numlines' lines are available, the whole file ist
1021        returned. If the file can not be opened or some other error
1022        occurs, empty list is returend.
1023        """
1024        result = []
1025        lines_hit = 0
1026
1027        # We only handle files in instances' log directory...
1028        logpath = os.path.join(i_home, "log")
1029        filename = str(os.path.abspath( os.path.join( logpath, filename )))
1030        if not filename.startswith( logpath ):
1031            # Attempt to access file outside log-dir...
1032            return []
1033
1034        try:
1035            fd = file( filename, "rb" )
1036        except IOError:
1037            return []
1038        if not fd:
1039            return []
1040
1041        if os.linesep == None:
1042            linesep = '\n'
1043        else:
1044            linesep = os.linesep
1045
1046        # Try to find 'numlines' times a lineseparator, searching from end
1047        # and moving to the beginning of file...
1048        fd.seek( 0, 2) # Move to end of file...
1049        while lines_hit < numlines:
1050            if fd.read(1) == linesep[-1]: # This moves filedescriptor
1051                                          # one step forward...
1052                lines_hit += 1
1053            try:
1054                fd.seek( -2, 1) # Go two bytes back from current pos...
1055            except IOError:
1056                # We cannot go back two bytes. Maybe the file is too small...
1057                break
1058        fd.seek(2,1)
1059
1060        # Read all lines from current position...
1061        result = fd.readlines()
1062        # Remove line endings...
1063        result = [x.strip() for x in result]
1064        fd.close()
1065        return result
1066    ###)
1067
[1700]1068    security.declareProtected(ModifyPortalContent,"getCallbacksFromLog")###(
[1665]1069    def getCallbacksFromLog(self,filename):
1070        """fix Online Payment Transactions from Z2.log entries"""
1071        import transaction
1072        import random
1073        from cgi import parse_qs
1074        from urlparse import urlparse
1075        #from pdb import set_trace
1076        wftool = self.portal_workflow
1077        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1078        students_folder = self.portal_url.getPortalObject().campus.students
1079        s = r'(?P<client_ip>\S+) - (?P<member_id>\S+) \['
1080        s += r'(?P<date>.*)\] "(?P<get>.*)" (?P<codes>\d+ \d+) "'
1081        s += r'(?P<intersw>.*)" "(?P<agent>.*)"'
1082        data = re.compile(s)
1083        start = True
1084        tr_count = 1
1085        total = 0
1086        #name = 'pume_results'
1087        #name = 'epaymentsuccessful_z2log2'
1088        name = filename
1089        no_import = []
1090        imported = []
1091        logger = logging.getLogger('WAeUPTool.getFailedTransactions')
1092        try:
1093            transactions = open("%s/import/%s" % (i_home,name),"rb").readlines()
1094        except:
1095            logger.error('Error reading %s' % name)
1096            return
1097        tas = []
1098        for line in transactions:
1099            dict = {}
1100            items = data.search(line)
1101            dict['idict'] = idict = items.groupdict()
1102            #print idict
1103            #from pdb import set_trace;set_trace()
1104            urlparsed = urlparse(idict['get'][4:])
1105            #print urlparsed
1106            path = urlparsed[2].split('/')
1107            dict['student_id'] = student_id = path[8]
1108            dict['payment_id'] = payment_id = path[10]
1109            dict['qs_dict'] = qs_dict = parse_qs(urlparsed[4])
1110            tas.append(dict)
1111            tr_count += 1
1112        return tas
1113    ###)
1114
[1620]1115    security.declareProtected(ModifyPortalContent,"importOnlinePaymentTransactions")###(
1116    def importOnlinePaymentTransactions(self):
1117        """load Online Payment Transactions from CSV values"""
1118        import transaction
1119        import random
1120        #from pdb import set_trace
1121        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
[1625]1122        opt = self.online_payments_import
[1620]1123        students_folder = self.portal_url.getPortalObject().campus.students
1124        start = True
1125        tr_count = 1
1126        total = 0
1127        #name = 'pume_results'
1128        name = 'OnlineTransactions'
1129        no_import = []
1130        imported = []
1131        logger = logging.getLogger('WAeUPTool.importOnlinePaymentTransactions')
1132        try:
1133            transactions = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
1134        except:
1135            logger.error('Error reading %s.csv' % name)
1136            return
1137        for pay_transaction in transactions:
1138            if start:
1139                start = False
1140                logger.info('Start loading from %s.csv' % name)
1141                s = ','.join(['"%s"' % fn for fn in pay_transaction.keys()])
1142                no_import.append('%s,"Error"' % s)
1143                format = ','.join(['"%%(%s)s"' % fn for fn in pay_transaction.keys()])
1144                format_error = format + ',"%(Error)s"'
1145            data = {}
[1644]1146
[1781]1147            # format of the first file sent by Tayo
[1643]1148            #data['datetime'] = date = DateTime.DateTime(pay_transaction['Date'])
1149            #data['student_id'] = student_id = pay_transaction['Payer ID']
1150            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
1151            #data['response_code'] = response_code = pay_transaction['Resp Code']
1152            #data['amount'] = amount = pay_transaction['Amount']
[1644]1153
[1781]1154            # format of the second file sent by Tayo
[1798]1155            #data['datetime'] = date = 0
1156            #data['student_id'] = student_id = pay_transaction['Payer ID']
1157            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
1158            #data['response_code'] = response_code = '00'
1159            #data['amount'] = amount = pay_transaction['Amount']
[1813]1160
[1798]1161            # format of the third file sent by Kehinde
[1643]1162            data['datetime'] = date = 0
[1798]1163            data['student_id'] = student_id = pay_transaction['customer_id']
1164            data['order_id'] = order_id = pay_transaction['merchant_reference']
[1644]1165            data['response_code'] = response_code = '00'
[1813]1166            data['amount'] = amount = pay_transaction['Amount']
[1644]1167
[1620]1168            dup = False
1169            if response_code == "12":
1170                continue
1171            try:
1172                opt.addRecord(**data)
1173            except ValueError:
1174                dup = True
1175            #from pdb import set_trace;set_trace()
1176            if dup:
1177                if response_code == "00":
[1798]1178                    try:
1179                        opt.modifyRecord(**data)
1180                    except:
1181                        logger.info("duplicate uid, order_id %(order_id)s, student_id %(student_id)s, response_code %(response_code)s" % data)
1182                        continue
[1620]1183                else:
[1674]1184                    pay_transaction['Error'] = "Duplicate order_id"
[1620]1185                    no_import.append( format_error % pay_transaction)
[1674]1186                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
[1620]1187                    continue
1188            tr_count += 1
1189            if tr_count > 1000:
1190                if len(no_import) > 0:
1191                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1192                             '\n'.join(no_import) + '\n')
1193                    no_import = []
[1645]1194                em = '%d transactions committed\n' % (tr_count)
[1620]1195                transaction.commit()
1196                regs = []
1197                logger.info(em)
1198                total += tr_count
1199                tr_count = 0
1200        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1201                                                '\n'.join(no_import))
1202        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
1203    ###)
[2237]1204
[2264]1205    security.declareProtected(ModifyPortalContent,'mass_create_faculty') ###(
1206    def mass_create_faculty(self,mapping):
1207        "create a faculty"
1208        logger = logging.getLogger('WAeUPTool.mass_create_faculty')
1209        academics_folder = self.portal_url.getPortalObject().campus.academics
1210        fid = mapping['code']
1211        if getattr(academics_folder,fid,None) is not None:
1212            return '', "Faculty with ID: %s exists" % fid
[2267]1213        logger.info('Creating Faculty %(code)s, %(title)s' % mapping)
[2283]1214        try:
1215            academics_folder.invokeFactory('Faculty', fid)
1216        except BadRequest,E:
1217            return '', "%s" % E
[2264]1218        f = getattr(academics_folder,fid,None)
1219        f.getContent().edit(mapping=mapping)
1220        return fid,''
1221    ###)
1222
[2288]1223    security.declareProtected(ModifyPortalContent,'mass_edit_faculty') ###(
[2264]1224    def mass_edit_faculty(self,mapping):
1225        "edit a faculty"
1226        logger = logging.getLogger('WAeUPTool.mass_edit_faculty')
1227        academics_folder = self.portal_url.getPortalObject().campus.academics
1228        fid = mapping['code']
1229        f = getattr(academics_folder,fid,None)
1230        if f is None:
1231            return '', "Faculty with ID: %s does not exist" % fid
[2267]1232        logger.info('Editing Faculty %(code)s, %(title)s' % mapping)
[2264]1233        f.getContent().edit(mapping=mapping)
1234        return fid,''
1235    ###)
1236
[2234]1237    security.declareProtected(ModifyPortalContent,'mass_create_department') ###(
[2193]1238    def mass_create_department(self,mapping):
1239        "create a department in the correct faculty"
1240        logger = logging.getLogger('WAeUPTool.mass_create_department')
1241        fid = mapping['faculty_code']
1242        if getattr(self,'_v_faculties',None) is None:
1243            res = self.portal_catalog(portal_type = "Faculty")
1244            self._v_faculties = {}
1245            for f in res:
1246                self._v_faculties[f.getId] = f.getObject()
1247        f = self._v_faculties.get(fid,None)
1248        if f is None:
1249            return '', "No Faculty with ID: %s" % fid
1250        else:
1251            did = mapping.get('code')
1252            d = getattr(f,did,None)
1253            if d is None or d.portal_type == "Faculty":
[2267]1254                logger.info('Creating Department %(code)s, %(title)s' % mapping)
[2283]1255                try:
1256                    f.invokeFactory('Department', did)
1257                except BadRequest,E:
1258                    return '', "%s" % E
[2193]1259                d = getattr(f,did)
1260                d.invokeFactory('CoursesFolder','courses')
1261                courses = getattr(d,'courses')
1262                dict = {'Title': 'Courses'}
1263                courses.getContent().edit(mapping=dict)
1264                d.invokeFactory('CertificatesFolder','certificates')
1265                certificates = getattr(d,'certificates')
1266                dict = {'Title': 'Certificates'}
1267                certificates.getContent().edit(mapping=dict)
1268            d.getContent().edit(mapping=mapping)
1269        return did,''
1270    ###)
[1620]1271
[2234]1272    security.declareProtected(ModifyPortalContent,'mass_edit_department') ###(
[2193]1273    def mass_edit_department(self,mapping):
1274        "create a department in the correct faculty"
1275        logger = logging.getLogger('WAeUPTool.mass_create_department')
1276        academics_folder = self.portal_url.getPortalObject().campus.academics
1277        fid = mapping['faculty_code']
1278        did = mapping.get('code')
1279        try:
1280            d = getattr(getattr(academics_folder,fid),did,None)
1281        except KeyError:
1282            return '', "Department %s or Faculty %s wrong" % (did,fid)
1283        else:
1284            if d is None or d.portal_type == "Faculty":
[2267]1285                logger.info('Editing Department %(code)s, %(title)s' % mapping)
[2193]1286            d.getContent().edit(mapping=mapping)
1287        return did,''
1288    ###)
[1786]1289
[2265]1290    security.declareProtected(ModifyPortalContent,'mass_create_course') ###(
1291    def mass_create_course(self,mapping):
[2315]1292        #import pdb;pdb.set_trace()
[2265]1293        if getattr(self,'_v_course_list',None) is None:
1294            self._v_course_list = []
1295        if getattr(self,'_v_departments',None) is None:
1296            res = self.portal_catalog(portal_type = "Department")
[2313]1297            self._v_department_courses = {}
[2265]1298            for d in res:
[2313]1299                self._v_department_courses[d.getId] = getattr(d.getObject(),"courses",None)
[2265]1300        did = mapping['department_code']
[2313]1301        d = self._v_department_courses.get(did,None)
[2265]1302        if d is None:
[2282]1303            return '', "No Department with ID: %s" % did
[2265]1304        course_id = mapping.get('code')
1305        if course_id in self._v_course_list:
[2313]1306            return '', "Duplicate Course ID: %s" % did
[2265]1307        c = getattr(d,course_id,None)
1308        if c is not None:
[2313]1309            return '', "Duplicate Course ID: %s" % did
[2283]1310        try:
1311            d.invokeFactory('Course', course_id)
1312        except BadRequest,E:
1313            return '', "%s" % E
[2265]1314        self._v_course_list.append(course_id)
1315        c = getattr(d,course_id)
1316        c.getContent().edit(mapping=mapping)
1317        return course_id,''
1318    ###)
1319
[2282]1320    security.declareProtected(ModifyPortalContent,'mass_edit_course') ###(
1321    def mass_edit_course(self,mapping):
1322        #import pdb;pdb.set_trace()
1323        course_id = mapping.get('code')
1324        res = self.portal_catalog(id=course_id)
1325        if not res:
[2289]1326            return '', "No Course with ID: %s" % course_id
[2282]1327        c = res[0].getObject()
1328        c.getContent().edit(mapping=mapping)
1329        return course_id,''
1330    ###)
1331
1332    security.declareProtected(ModifyPortalContent,'mass_create_certificate') ###(
1333    def mass_create_certificate(self,mapping):
1334        if getattr(self,'_v_certificate_list',None) is None:
1335            self._v_certificate_list = []
[2313]1336        if getattr(self,'_v_department_certificates',None) is None:
[2282]1337            res = self.portal_catalog(portal_type = "Department")
[2313]1338            self._v_department_certificates = {}
[2282]1339            for d in res:
[2313]1340                self._v_department_certificates[d.getId] = getattr(d.getObject(),"certificates",None)
[2282]1341        did = mapping['department_code']
[2313]1342        d = self._v_department_certificates.get(did,None)
[2282]1343        if d is None:
1344            return '', "No Department with ID: %s" % did
1345        certificate_id = mapping.get('code')
1346        if certificate_id in self._v_certificate_list:
[2313]1347            return '', "Duplicate Certificate ID: %s" % did
[2282]1348        c = getattr(d,certificate_id,None)
1349        if c is not None:
[2313]1350            return '', "Duplicate Certificate ID: %s" % did
[2283]1351        try:
1352            d.invokeFactory('Certificate', certificate_id)
1353        except BadRequest,E:
1354            return '', "%s" % E
[2282]1355        self._v_certificate_list.append(certificate_id)
1356        c = getattr(d,certificate_id)
1357        c.getContent().edit(mapping=mapping)
1358        return certificate_id,''
1359    ###)
1360
1361    security.declareProtected(ModifyPortalContent,'mass_edit_certificate') ###(
1362    def mass_edit_certificate(self,mapping):
1363        #import pdb;pdb.set_trace()
1364        certificate_id = mapping.get('code')
1365        res = self.portal_catalog(id=certificate_id)
1366        if not res:
1367            return '', "No Certificate with ID: %s" % did
1368        c = res[0].getObject()
1369        c.getContent().edit(mapping=mapping)
1370        return certificate_id,''
1371    ###)
1372
[2520]1373    security.declareProtected(ModifyPortalContent,'mass_create_application') ###(
1374    def mass_create_application(self,mapping):
[2514]1375        #import pdb;pdb.set_trace()
[2547]1376        reg_no = mapping.get('reg_no')
[2514]1377        try:
1378            self.applicants_catalog.addRecord(**mapping)
1379        except ValueError:
[2548]1380            return '', "applicant record with reg_no %s already exists" % reg_no
[2546]1381        return reg_no,''
[2514]1382    ###)
1383
[2520]1384    security.declareProtected(ModifyPortalContent,'mass_edit_application') ###(
1385    def mass_edit_application(self,mapping):
[2514]1386        #import pdb;pdb.set_trace()
1387        reg_no = mapping.get('reg_no')
1388        try:
1389            self.applicants_catalog.modifyRecord(**mapping)
1390        except KeyError:
[2548]1391            return '', "applicant record with reg_no %s does not exist" % reg_no
[2514]1392        return reg_no,''
1393    ###)
1394
[2501]1395    security.declareProtected(ModifyPortalContent,'mass_create_course_result') ###(
1396    def mass_create_course_result(self,mapping):
[2500]1397        #import pdb;pdb.set_trace()
[2501]1398        if getattr(self,'_v_courses',None) is None:
1399            res = self.courses_catalog()
1400            self._v_courses = {}
1401            for brain in res:
[2520]1402                self._v_courses[brain.code] = brain
[2500]1403        course_id = mapping.get('code')
[2501]1404        if course_id not in self._v_courses.keys():
1405            return '', "No course with ID: %s" % did
1406        id_key = ''
1407        for id_key in ('student_id','matric_no'):
1408            id_field = mapping.get(id_key,None)
1409            if id_field is not None:
1410                student_id = id_field
1411                break
1412        query = Eq(id_key,id_field)
1413        res = self.students_catalog.evalAdvancedQuery(query)
1414        if not res:
1415            return '', "No student with %(id_field)s: %(id_key)s" % vars()
1416        if id_field != "student_id":
1417            mapping['student_id'] = res[0].id
1418        mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % mapping
1419        for k in ('semester',):
1420            mapping[k] = getattr(self._v_courses[course_id],k)
[2500]1421        try:
[2501]1422            self.course_results.addRecord(**mapping)
1423        except ValueError:
1424            return '', "course result already exists: %s" % key
1425        return key,''
[2500]1426    ###)
1427
1428    security.declareProtected(ModifyPortalContent,'mass_edit_course_result') ###(
1429    def mass_edit_course_result(self,mapping):
1430        #import pdb;pdb.set_trace()
1431        # if getattr(self,'_v_courses',None) is None:
1432        #     res = self.courses_catalog()
1433        #     self._v_courses = {}
1434        #     for brain in res:
[2520]1435        #         self._v_courses[brain.code] = brain
[2500]1436        # course_id = mapping.get('code')
1437        # if course_id not in self._v_courses.keys():
1438        #     return '', "No course with ID: %s" % did
1439        id_key = ''
1440        for id_key in ('student_id','matric_no'):
1441            id_field = mapping.get(id_key,None)
1442            if id_field is not None:
1443                student_id = id_field
1444                break
1445        query = Eq(id_key,id_field)
1446        res = self.students_catalog.evalAdvancedQuery(query)
1447        if not res:
1448            return '', "No student with %(id_field)s: %(id_key)s" % vars()
1449        if id_field != "student_id":
1450            mapping['student_id'] = res[0].id
1451        mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % mapping
1452        # for k in ('semester',):
1453        #     mapping[k] = getattr(self._v_courses[course_id],k)
1454        try:
1455            self.course_results.modifyRecord(**mapping)
1456        except KeyError:
1457            return '', "No course result to edit: %s" % key
1458        return key,''
1459    ###)
1460
[2282]1461    security.declareProtected(ModifyPortalContent,'mass_create_certificate_course') ###(
1462    def mass_create_certificate_course(self,mapping):
[2320]1463        if getattr(self,'_v_courses',None) is None:
1464            res = self.courses_catalog()
[2351]1465            self._v_courses= [course.code for course in res]
[2282]1466        if getattr(self,'_v_ceritficates',None) is None:
1467            res = self.portal_catalog(portal_type = "Certificate")
1468            self._v_certificates = {}
1469            for cert in res:
1470                self._v_certificates[cert.getId] = cert.getObject()
[2284]1471        certificate_course_id = mapping.get('code')
[2351]1472        if certificate_course_id not in self._v_courses:
[2284]1473            return '', "No Course with ID: %s" % certificate_course_id
[2282]1474        cert_id = mapping['certificate_code']
1475        cert = self._v_certificates.get(cert_id,None)
1476        if cert is None:
[2284]1477            return '', "No Certificate with ID: %s" % cert_id
[2282]1478        level_id = mapping.get('level')
1479        level = getattr(cert,level_id,None)
1480        if level is None:
1481            cert.invokeFactory('StudyLevel', level_id)
1482            level = getattr(cert,level_id,None)
1483        elif hasattr(level,certificate_course_id):
1484            return '', "Duplicate CertificateCourse ID: %s in %s/ %s" %\
1485            (certificate_course_id,cert_id,level_id)
1486        level.invokeFactory('CertificateCourse', certificate_course_id)
1487        c = getattr(level,certificate_course_id)
1488        c.getContent().edit(mapping=mapping)
1489        return certificate_course_id,''
1490    ###)
1491
[2193]1492    field2types_student = {   ###(
[1756]1493                      'StudentApplication':
1494                          {'id': 'application',
1495                           'title': 'Application Data',
[1991]1496                           'wf_transition_return': 'close',
1497                           'wf_transition_admit': 'remain',
[1756]1498                           'fields':
1499                             ('jamb_reg_no',
1500                              'entry_mode',
1501                              'entry_session',
1502                              'jamb_score',
[1786]1503                              'app_email',
[2008]1504                              'jamb_age',
[2428]1505                              'jamb_state',
1506                              'jamb_lga',
[1756]1507                              )
1508                              },
[1786]1509                      #'StudentPume':
1510                      #    {'id': 'pume',
1511                      #     'title': 'Pume Data',
[1991]1512                      #     'wf_transition_return': 'close',
1513                      #     'wf_transition_admit': 'close',
[1786]1514                      #     'fields':
1515                      #       ('pume_score',
1516                      #        )
1517                      #        },
[1756]1518                      'StudentClearance':
1519                          {'id': 'clearance',
[2009]1520                           'title': 'Clearance/Eligibility Record',
[1991]1521                           'wf_transition_return': 'close',
1522                           'wf_transition_admit': 'remain',
[1756]1523                           'fields':
1524                             ('matric_no',
1525                              'nationality',
1526                              'lga',
[1804]1527                              'birthday',
[1756]1528                              )
1529                              },
1530                         'StudentPersonal':
1531                          {'id': 'personal',
1532                           'title': 'Personal Data',
[1991]1533                           'wf_transition_return': 'open',
1534                           'wf_transition_admit': 'remain',
[1756]1535                           'fields':
1536                             ('firstname',
1537                              'middlename',
1538                              'lastname',
1539                              'sex',
1540                              'email',
1541                              'phone',
1542                              'perm_address',
1543                              )
1544                              },
1545                         'StudentStudyCourse':
1546                          {'id': 'study_course',
1547                           'title': 'Study Course',
[1991]1548                           'wf_transition_return': 'open',
1549                           'wf_transition_admit': 'remain',
[1756]1550                           'fields':
1551                             ('study_course',
1552                              'current_level',
1553                              'current_session',
1554                              'current_mode',
1555                              'current_verdict',
[2478]1556                              'previous_verdict',
[1756]1557                              )
1558                              },
[1898]1559
1560                         'PaymentsFolder':
1561                          {'id': 'payments',
1562                           'title': 'Payments',
[1991]1563                           'wf_transition_return': 'open',
1564                           'wf_transition_admit': 'open',
[1898]1565                           'fields':
1566                             ()
1567                              },
[1756]1568                         }
1569    ###)
1570
[2193]1571    security.declareProtected(ModifyPortalContent,'mass_create_student') ###(
1572    def mass_create_student(self,mapping):
[1781]1573        "create a students record due import"
[2193]1574        logger = logging.getLogger('WAeUPTool.mass_create_student')
[1747]1575        students_folder = self.portal_url.getPortalObject().campus.students
[1818]1576        jamb_reg_no = mapping.get('jamb_reg_no',None)
[1747]1577        if jamb_reg_no:
1578            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1579            if res:
[1749]1580                return '',"jamb_reg_no exists"
[1818]1581        matric_no = mapping.get('matric_no',None)
[1747]1582        if matric_no:
1583            res = self.students_catalog(matric_no = matric_no)
1584            if res:
[1749]1585                return '',"matric_no exists"
[1747]1586        sid = self.waeup_tool.generateStudentId('?')
1587        students_folder.invokeFactory('Student', sid)
1588        student_obj = getattr(students_folder,sid)
[2193]1589        f2t = self.field2types_student
[1772]1590        d = {}
[1990]1591        transition = mapping.get('reg_transition','admit')
1592        if transition not in ('admit','return'):
[2008]1593            return '',"no valid transition provided"
[1747]1594        for pt in f2t.keys():
1595            student_obj.invokeFactory(pt,f2t[pt]['id'])
1596            sub_obj = getattr(student_obj,f2t[pt]['id'])
1597            sub_doc = sub_obj.getContent()
[1772]1598            d['Title'] = f2t[pt]['title']
[1747]1599            for field in f2t[pt]['fields']:
[1818]1600                d[field] = mapping.get(field,'')
[2454]1601
1602            if pt == "StudentApplication":
[2436]1603                d['jamb_sex']  = 'M'
1604                if mapping.get('sex'):
1605                    d['jamb_sex']  = 'F'
1606                d['jamb_firstname'] = mapping.get('firstname',None)
1607                d['jamb_middlename'] = mapping.get('middlename',None)
1608                d['jamb_lastname'] = mapping.get('lastname',None)
1609
[2433]1610            # if pt == "StudyCourse":
1611            #     for von,zu in (('entry_mode','current_mode'),
1612            #                    ('entry_session','current_session')):
1613            #         if mapping.get(zu,None) is None and mapping.get(von,None) is not None:
1614            #             d[zu] = mapping[von]
[1747]1615            sub_doc.edit(mapping = d)
[1990]1616
[1987]1617            #import pdb;pdb.set_trace()
1618            new_state = f2t[pt]['wf_transition_%(transition)s' % vars()]
[1898]1619            if new_state != "remain":
1620                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
[1990]1621        self.portal_workflow.doActionFor(student_obj,transition)
[1747]1622        student_obj.manage_setLocalRoles(sid, ['Owner',])
1623        return sid,''
1624    ###)
1625
[2193]1626    security.declareProtected(ModifyPortalContent,'mass_edit_student') ###(
1627    def mass_edit_student(self,mapping):
[1781]1628        "edit a students record due import"
[2193]1629        logger = logging.getLogger('WAeUPTool.mass_edit_student')
[1774]1630        students_folder = self.portal_url.getPortalObject().campus.students
[1818]1631        sid = mapping.get('id',None)
1632        jamb_reg_no = mapping.get('jamb_reg_no',None)
1633        matric_no = mapping.get('matric_no',None)
[1875]1634        editable_keys = mapping.keys()
[1774]1635        if sid:
1636            res = self.students_catalog(id = sid)
1637            if not res:
1638                return '',"no student with id %s" % sid
[2268]1639            if matric_no and res[0].matric_no and\
[1774]1640              matric_no != res[0].matric_no:
[2268]1641                logger.info("%s, old matric_no %s overwritten with %s" % (res[0].id,res[0].matric_no,matric_no))
1642            if jamb_reg_no and res[0].jamb_reg_no and\
[1774]1643              jamb_reg_no != res[0].jamb_reg_no:
[2268]1644                logger.info("%s, old reg_no %s overwritten with %s" % (res[0].id,res[0].jamb_reg_no,jamb_reg_no))
[1844]1645        elif jamb_reg_no:
1646            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1647            if not res:
1648                return '',"no student with jamb_reg_no %s" % jamb_reg_no
[1875]1649            editable_keys.remove('jamb_reg_no')
[1774]1650        elif matric_no:
1651            res = self.students_catalog(matric_no = matric_no)
1652            if not res:
1653                return '',"no student with matric_no %s" % matric_no
[1875]1654            editable_keys.remove('matric_no')
[1965]1655
[2268]1656        ## included only to change wf state from admitted to returning
1657        #if res[0].review_state not in ('admitted','objection_raised'):
1658        #    return '%s' % res[0].id ,"student is not in state admitted or objection_raised"
1659        ## end inclusion
[1965]1660
[1774]1661        sid = res[0].id
1662        student_obj = getattr(students_folder,sid)
[2193]1663        f2t = self.field2types_student
[1774]1664        d = {}
[2265]1665        #import pdb;pdb.set_trace()
[1875]1666        any_change = False
[1774]1667        for pt in f2t.keys():
[1875]1668            if pt == "student_application":
1669                d['jamb_sex']  = 'M'
1670                if mapping.get('sex'):
1671                    d['jamb_sex']  = 'F'
1672            intersect = set(f2t[pt]['fields']).intersection(set(editable_keys))
1673            if intersect:
1674                sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1675                if sub_obj is None:
1676                    try:
1677                        student_obj.invokeFactory(pt,f2t[pt]['id'])
1678                    except:
1679                        continue
1680                    sub_obj = getattr(student_obj,f2t[pt]['id'])
1681                    d['Title'] = f2t[pt]['title']
1682                sub_doc = sub_obj.getContent()
1683                for field in intersect:
1684                    changed = False
[2478]1685                    if getattr(sub_doc,field,None) != mapping.get(field,''):
[1875]1686                        any_change = True
1687                        changed = True
1688                        d[field] = mapping.get(field,'')
1689                    if changed:
1690                        sub_doc.edit(mapping = d)
[1904]1691
[1905]1692
[2268]1693        ## included only to change wf state from admitted to returning
1694        #    if res[0].review_state in ('admitted','objection_raised'):
1695        #        new_state = f2t[pt]['wf_transition_return']
1696        #        sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1697        #        if sub_obj and new_state != "remain":
1698        #            try:
1699        #                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1700        #            except:
1701        #                #logger.info('%s, wf transition %s of %s failed' % (sid,new_state,sub_obj.id))
1702        #                pass
1703        #if res[0].review_state in ('admitted','objection_raised'):
1704        #    wfaction = 'return'
1705        #    try:
1706        #        self.portal_workflow.doActionFor(student_obj,wfaction)
1707        #        logger.info('%s, wf state changed' % sid)
1708        #        any_change = True
1709        #    except:
1710        #        logger.info('%s, wf transition failed, old state = %s' % (sid,res[0].review_state))
1711        #        pass
1712        ## end inclusion
[1904]1713
[1905]1714
[1875]1715        if any_change:
1716            return sid,''
1717        else:
1718            return sid,'not modified'
[1774]1719    ###)
[1905]1720
[1730]1721    security.declareProtected(ModifyPortalContent,"importData")###(
[2259]1722    def importData(self,filename,name,edit=False,bypass_queue_catalog=False):
[1730]1723        """load data from CSV values"""
1724        import transaction
1725        import random
[1775]1726
[1773]1727        pm = self.portal_membership
[1775]1728        member = pm.getAuthenticatedMember()
1729
[1747]1730        logger = logging.getLogger('WAeUPTool.importData')
[1730]1731        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1732        students_folder = self.portal_url.getPortalObject().campus.students
1733        start = True
[2495]1734        tr_count = 0
[1756]1735        total_imported = 0
1736        total_not_imported = 0
[1730]1737        total = 0
[1749]1738        iname = "import_%s" % name
[2528]1739        if iname == 'import_application':
1740            commit_after = 2000
1741        else:
1742            commit_after = 100
[1747]1743        stool = getToolByName(self, 'portal_schemas')
1744        ltool = getToolByName(self, 'portal_layouts')
1745        schema = stool._getOb(iname)
[1730]1746        if schema is None:
[1772]1747            em = 'No such schema %s' % iname
1748            logger.error('No such schema %s' % iname)
[1756]1749            return em
[1747]1750        layout = ltool._getOb(iname)
[1730]1751        if layout is None:
[1772]1752            em = 'No such layout %s' % iname
[1756]1753            logger.error(em)
1754            return em
[1730]1755        validators = {}
1756        for widget in layout.keys():
[1749]1757            validators[widget] = layout[widget].validate
[2193]1758        #import pdb;pdb.set_trace()
[2289]1759        mode = "create"
[1774]1760        if edit:
[2289]1761            mode = "edit"
1762        importer_name = "mass_%(mode)s_%(name)s" % vars()
[1772]1763        importer = getattr(self, '%s' % importer_name,None)
1764        if importer is None:
1765            em = 'No importer function %s' % importer_name
[1756]1766            logger.error(em)
1767            return em
[1747]1768        not_imported = []
[1730]1769        imported = []
1770        try:
[1747]1771            items = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
[1730]1772        except:
[1756]1773            em = 'Error reading %s.csv' % filename
1774            logger.error(em)
1775            return em
[1730]1776        for item in items:
1777            if start:
1778                start = False
[1747]1779                adapters = [MappingStorageAdapter(schema, item)]
[2315]1780                logger.info('%s starts import from %s.csv in %s mode with schema and layout %s' % (member,filename,mode,iname))
[2094]1781                attrs = csv.reader(open("%s/import/%s.csv" % (i_home,filename),"rb")).next()
1782                import_keys = [k for k in attrs if not k.startswith('ignore')]
[1804]1783                diff2schema = set(import_keys).difference(set(schema.keys()))
1784                diff2layout = set(import_keys).difference(set(layout.keys()))
1785                if diff2schema:
[2282]1786                    em = 'not ignorable key(s): "%s" found in heading' % ", ".join(diff2schema)
[1804]1787                    return em
[2433]1788                if mode == "create":
[2436]1789                    required_keys = [layout.getIdUnprefixed(id)
[2433]1790                                     for id,widget in layout.objectItems()
1791                                     if widget.is_required]
1792                    if not set(required_keys).issubset(set(import_keys)):
1793                        diff2import = set(required_keys).difference(set(import_keys))
1794                        em = 'required key(s): "%s" not found in heading' % ", ".join(diff2import)
1795                        return em
[1753]1796                s = ','.join(['"%s"' % fn for fn in import_keys])
[1772]1797                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(s + ',"Error"'+ '\n')
1798                s = '"id",' + s
[1756]1799                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
[1730]1800                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
1801                format_error = format + ',"%(Error)s"'
[1756]1802                format = '"%(id)s",'+ format
[2267]1803
[2094]1804            dm = DataModel(item, adapters,context=self)
[1747]1805            ds = DataStructure(data=item,datamodel=dm)
1806            error_string = ""
[2495]1807            total += 1
[1730]1808            for k in import_keys:
[2289]1809                if not validators[k](ds,mode=mode):
[2264]1810                    error_string += " %s : %s" % (k,
1811                                                  self.translation_service(ds.getError(k),
1812                                                                           ds.getErrorMapping(k)))
[1747]1813            if not error_string:
[2433]1814                temp_item = item.copy()
1815                temp_item.update(dm)
[2435]1816                temp_item['id'],error = importer(temp_item)
[1747]1817                if error:
1818                    error_string += error
[2433]1819                else:
1820                    item = temp_item
[2436]1821            if error_string:
[1747]1822                item['Error'] = error_string
1823                not_imported.append(format_error % item)
[1756]1824                total_not_imported += 1
[1747]1825            else:
[1821]1826                em = format % item
1827                imported.append(em)
[1875]1828                tr_count += 1
[1756]1829                total_imported += 1
[2495]1830                logger.info("%(total_imported)d of %(total)d %(em)s" % vars())
[2520]1831
[2528]1832            if total and not total % commit_after:
[1875]1833                transaction.commit()
[1747]1834                if len(not_imported) > 0:
1835                    open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1836                             '\n'.join(not_imported) + '\n')
1837                    not_imported = []
1838                if len(imported) > 0:
1839                    open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
[1772]1840                             '\n'.join(imported) + '\n')
[1747]1841                    imported = []
[1730]1842                em = '%d transactions committed\n' % (tr_count)
1843                regs = []
1844                logger.info(em)
1845                tr_count = 0
[2528]1846                #if total > 100:
1847                #    return
[1756]1848        if len(imported) > 0:
[1747]1849            open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
1850                                                '\n'.join(imported))
[1756]1851        if len(not_imported) > 0:
[1747]1852            open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1853                                                '\n'.join(not_imported))
[2496]1854        em = "Finished: %d imported, %d not imported (of total %d)" % (total_imported,total_not_imported,total)
[2495]1855        logger.info(em)
[1756]1856        return em
[1730]1857    ###)
1858
[2292]1859    security.declareProtected(ModifyPortalContent,"moveImagesToFS")###(
1860    def moveImagesToFS(self,student_id="O738726"):
1861        "move the images to the filesystem"
[2675]1862        images_dir = getImagesDir(student_id)
1863        #images_dir = os.path.join("%s" % images_base,student_id)
[2292]1864        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1865        stool = getToolByName(self, 'portal_schemas')
1866        schemas = ['student_application',
1867                   'student_clearance',
1868                   ]
1869        created = False
1870        for schema_id in schemas:
1871            schema = stool._getOb(schema_id)
1872            object = getattr(student_folder,schema_id[len('student_'):],None)
1873            if object is None:
1874                continue
1875            doc = object.getContent()
1876            for key in schema.keys():
1877                if schema[key].meta_type != "CPS Image Field":
1878                    continue
1879                #import pdb;pdb.set_trace()
[2351]1880                image = getattr(doc,key,None)
1881                if not image or not hasattr(image,"data"):
[2292]1882                    continue
1883                if not created:
1884                    if not os.path.exists(images_dir):
1885                        os.mkdir(images_dir)
1886                    created = True
1887                filename = os.path.join(images_dir,"%(key)s_%(student_id)s.jpg" % vars())
1888                open(filename,"wb").write(str(image.data))
[2500]1889    ###)
[2292]1890
[2300]1891    security.declareProtected(ModifyPortalContent,"movePassportToFS")###(
1892    def movePassportToFS(self,student_id="O738726"):
1893        "move the passports to the filesystem"
1894        images_dir = os.path.join("%s" % i_home,'passports')
1895        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1896        stool = getToolByName(self, 'portal_schemas')
1897        schemas = ['student_application',
1898                   #'student_clearance',
1899                   ]
1900        created = False
1901        for schema_id in schemas:
1902            schema = stool._getOb(schema_id)
1903            object = getattr(student_folder,schema_id[len('student_'):],None)
1904            if object is None:
1905                continue
1906            doc = object.getContent()
1907            for key in schema.keys():
1908                if schema[key].meta_type != "CPS Image Field":
1909                    continue
1910                #import pdb;pdb.set_trace()
1911                image = getattr(doc,key)
1912                if not hasattr(image,"data"):
1913                    continue
1914                if not created:
1915                    if not os.path.exists(images_dir):
1916                        os.mkdir(images_dir)
1917                    created = True
1918                filename = os.path.join(images_dir,"%(student_id)s.jpg" % vars())
1919                open(filename,"wb").write(str(image.data))
[2500]1920    ###)
[2300]1921
[828]1922InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.