source: WAeUP_SRP/base/WAeUPTool.py @ 2677

Last change on this file since 2677 was 2677, checked in by joachim, 17 years ago

fix picturesList

  • Property svn:keywords set to Id
File size: 79.0 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 2677 2007-11-16 12:05:36Z 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()
[2677]968        #picture_path = os.path.join(i_home,path,student_id)
969        picture_path = getImagesDir(student_id)
[2364]970        if not os.path.exists(picture_path):
971            return []
972        return [picture[:picture.rfind('_')] for picture in os.listdir(picture_path)]
973    ###)
974
[2114]975    security.declarePublic('showFsPicture') ###(
976    def showFsPicture(self,path):
977        """return a picture from the filesystem"""
[2675]978        #picture_path = os.path.join(i_home,path)
979        picture_path = os.path.join(images_base,path)
[2335]980        response = self.REQUEST.RESPONSE
[2342]981        #import pdb;pdb.set_trace()
[2354]982        registry = getToolByName(self, 'mimetypes_registry')
983        mimetype = str(registry.lookupExtension(path.lower()) or
984                    registry.lookupExtension('file.bin'))
[2114]985        if os.path.exists(picture_path):
[2354]986            response.setHeader('Content-type',mimetype)
[2114]987            return open(picture_path).read()
[2335]988        picture_path = os.path.join(i_home,'import',path)
989        if os.path.exists(picture_path):
990            return open(picture_path).read()
[2114]991    ###)
992
[1151]993    security.declareProtected(ModifyPortalContent,'deleteAllCourses') ###(
994    def deleteAllCourses(self,department="All"):
995        ''' delete the courses'''
996        pm = self.portal_membership
997        member = pm.getAuthenticatedMember()
[1160]998
[1151]999        if str(member) not in ("henrik","joachim"):
1000            return "not possible"
1001        if department == "All":
1002            res = self.portal_catalog({'meta_type': 'Department'})
1003        if len(res) < 1:
1004            return "No Departments found"
[1160]1005
[1151]1006        deleted = []
1007        for dep in res:
1008            cf = dep.getObject().courses
1009            if cf:
1010                cf.manage_delObjects(ids=cf.objectIds())
1011                deleted.append("deleted Courses in %s" % dep.getId)
1012        return "\r".join(deleted)
[1160]1013    ###)
[1151]1014
[1572]1015    security.declareProtected(ModifyPortalContent,'getLogfileLines') ###(
1016    def getLogfileLines(self,filename="event.log",numlines=20):
1017        """Get last NUMLINES lines of logfile FILENAME.
[1160]1018
[1572]1019        Return last lines' of a file in the instances logfile directory as
1020        a list. The number of returned lines equals `numlines' or less. If
1021        less than `numlines' lines are available, the whole file ist
1022        returned. If the file can not be opened or some other error
1023        occurs, empty list is returend.
1024        """
1025        result = []
1026        lines_hit = 0
1027
1028        # We only handle files in instances' log directory...
1029        logpath = os.path.join(i_home, "log")
1030        filename = str(os.path.abspath( os.path.join( logpath, filename )))
1031        if not filename.startswith( logpath ):
1032            # Attempt to access file outside log-dir...
1033            return []
1034
1035        try:
1036            fd = file( filename, "rb" )
1037        except IOError:
1038            return []
1039        if not fd:
1040            return []
1041
1042        if os.linesep == None:
1043            linesep = '\n'
1044        else:
1045            linesep = os.linesep
1046
1047        # Try to find 'numlines' times a lineseparator, searching from end
1048        # and moving to the beginning of file...
1049        fd.seek( 0, 2) # Move to end of file...
1050        while lines_hit < numlines:
1051            if fd.read(1) == linesep[-1]: # This moves filedescriptor
1052                                          # one step forward...
1053                lines_hit += 1
1054            try:
1055                fd.seek( -2, 1) # Go two bytes back from current pos...
1056            except IOError:
1057                # We cannot go back two bytes. Maybe the file is too small...
1058                break
1059        fd.seek(2,1)
1060
1061        # Read all lines from current position...
1062        result = fd.readlines()
1063        # Remove line endings...
1064        result = [x.strip() for x in result]
1065        fd.close()
1066        return result
1067    ###)
1068
[1700]1069    security.declareProtected(ModifyPortalContent,"getCallbacksFromLog")###(
[1665]1070    def getCallbacksFromLog(self,filename):
1071        """fix Online Payment Transactions from Z2.log entries"""
1072        import transaction
1073        import random
1074        from cgi import parse_qs
1075        from urlparse import urlparse
1076        #from pdb import set_trace
1077        wftool = self.portal_workflow
1078        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1079        students_folder = self.portal_url.getPortalObject().campus.students
1080        s = r'(?P<client_ip>\S+) - (?P<member_id>\S+) \['
1081        s += r'(?P<date>.*)\] "(?P<get>.*)" (?P<codes>\d+ \d+) "'
1082        s += r'(?P<intersw>.*)" "(?P<agent>.*)"'
1083        data = re.compile(s)
1084        start = True
1085        tr_count = 1
1086        total = 0
1087        #name = 'pume_results'
1088        #name = 'epaymentsuccessful_z2log2'
1089        name = filename
1090        no_import = []
1091        imported = []
1092        logger = logging.getLogger('WAeUPTool.getFailedTransactions')
1093        try:
1094            transactions = open("%s/import/%s" % (i_home,name),"rb").readlines()
1095        except:
1096            logger.error('Error reading %s' % name)
1097            return
1098        tas = []
1099        for line in transactions:
1100            dict = {}
1101            items = data.search(line)
1102            dict['idict'] = idict = items.groupdict()
1103            #print idict
1104            #from pdb import set_trace;set_trace()
1105            urlparsed = urlparse(idict['get'][4:])
1106            #print urlparsed
1107            path = urlparsed[2].split('/')
1108            dict['student_id'] = student_id = path[8]
1109            dict['payment_id'] = payment_id = path[10]
1110            dict['qs_dict'] = qs_dict = parse_qs(urlparsed[4])
1111            tas.append(dict)
1112            tr_count += 1
1113        return tas
1114    ###)
1115
[1620]1116    security.declareProtected(ModifyPortalContent,"importOnlinePaymentTransactions")###(
1117    def importOnlinePaymentTransactions(self):
1118        """load Online Payment Transactions from CSV values"""
1119        import transaction
1120        import random
1121        #from pdb import set_trace
1122        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
[1625]1123        opt = self.online_payments_import
[1620]1124        students_folder = self.portal_url.getPortalObject().campus.students
1125        start = True
1126        tr_count = 1
1127        total = 0
1128        #name = 'pume_results'
1129        name = 'OnlineTransactions'
1130        no_import = []
1131        imported = []
1132        logger = logging.getLogger('WAeUPTool.importOnlinePaymentTransactions')
1133        try:
1134            transactions = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
1135        except:
1136            logger.error('Error reading %s.csv' % name)
1137            return
1138        for pay_transaction in transactions:
1139            if start:
1140                start = False
1141                logger.info('Start loading from %s.csv' % name)
1142                s = ','.join(['"%s"' % fn for fn in pay_transaction.keys()])
1143                no_import.append('%s,"Error"' % s)
1144                format = ','.join(['"%%(%s)s"' % fn for fn in pay_transaction.keys()])
1145                format_error = format + ',"%(Error)s"'
1146            data = {}
[1644]1147
[1781]1148            # format of the first file sent by Tayo
[1643]1149            #data['datetime'] = date = DateTime.DateTime(pay_transaction['Date'])
1150            #data['student_id'] = student_id = pay_transaction['Payer ID']
1151            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
1152            #data['response_code'] = response_code = pay_transaction['Resp Code']
1153            #data['amount'] = amount = pay_transaction['Amount']
[1644]1154
[1781]1155            # format of the second file sent by Tayo
[1798]1156            #data['datetime'] = date = 0
1157            #data['student_id'] = student_id = pay_transaction['Payer ID']
1158            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
1159            #data['response_code'] = response_code = '00'
1160            #data['amount'] = amount = pay_transaction['Amount']
[1813]1161
[1798]1162            # format of the third file sent by Kehinde
[1643]1163            data['datetime'] = date = 0
[1798]1164            data['student_id'] = student_id = pay_transaction['customer_id']
1165            data['order_id'] = order_id = pay_transaction['merchant_reference']
[1644]1166            data['response_code'] = response_code = '00'
[1813]1167            data['amount'] = amount = pay_transaction['Amount']
[1644]1168
[1620]1169            dup = False
1170            if response_code == "12":
1171                continue
1172            try:
1173                opt.addRecord(**data)
1174            except ValueError:
1175                dup = True
1176            #from pdb import set_trace;set_trace()
1177            if dup:
1178                if response_code == "00":
[1798]1179                    try:
1180                        opt.modifyRecord(**data)
1181                    except:
1182                        logger.info("duplicate uid, order_id %(order_id)s, student_id %(student_id)s, response_code %(response_code)s" % data)
1183                        continue
[1620]1184                else:
[1674]1185                    pay_transaction['Error'] = "Duplicate order_id"
[1620]1186                    no_import.append( format_error % pay_transaction)
[1674]1187                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
[1620]1188                    continue
1189            tr_count += 1
1190            if tr_count > 1000:
1191                if len(no_import) > 0:
1192                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1193                             '\n'.join(no_import) + '\n')
1194                    no_import = []
[1645]1195                em = '%d transactions committed\n' % (tr_count)
[1620]1196                transaction.commit()
1197                regs = []
1198                logger.info(em)
1199                total += tr_count
1200                tr_count = 0
1201        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1202                                                '\n'.join(no_import))
1203        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
1204    ###)
[2237]1205
[2264]1206    security.declareProtected(ModifyPortalContent,'mass_create_faculty') ###(
1207    def mass_create_faculty(self,mapping):
1208        "create a faculty"
1209        logger = logging.getLogger('WAeUPTool.mass_create_faculty')
1210        academics_folder = self.portal_url.getPortalObject().campus.academics
1211        fid = mapping['code']
1212        if getattr(academics_folder,fid,None) is not None:
1213            return '', "Faculty with ID: %s exists" % fid
[2267]1214        logger.info('Creating Faculty %(code)s, %(title)s' % mapping)
[2283]1215        try:
1216            academics_folder.invokeFactory('Faculty', fid)
1217        except BadRequest,E:
1218            return '', "%s" % E
[2264]1219        f = getattr(academics_folder,fid,None)
1220        f.getContent().edit(mapping=mapping)
1221        return fid,''
1222    ###)
1223
[2288]1224    security.declareProtected(ModifyPortalContent,'mass_edit_faculty') ###(
[2264]1225    def mass_edit_faculty(self,mapping):
1226        "edit a faculty"
1227        logger = logging.getLogger('WAeUPTool.mass_edit_faculty')
1228        academics_folder = self.portal_url.getPortalObject().campus.academics
1229        fid = mapping['code']
1230        f = getattr(academics_folder,fid,None)
1231        if f is None:
1232            return '', "Faculty with ID: %s does not exist" % fid
[2267]1233        logger.info('Editing Faculty %(code)s, %(title)s' % mapping)
[2264]1234        f.getContent().edit(mapping=mapping)
1235        return fid,''
1236    ###)
1237
[2234]1238    security.declareProtected(ModifyPortalContent,'mass_create_department') ###(
[2193]1239    def mass_create_department(self,mapping):
1240        "create a department in the correct faculty"
1241        logger = logging.getLogger('WAeUPTool.mass_create_department')
1242        fid = mapping['faculty_code']
1243        if getattr(self,'_v_faculties',None) is None:
1244            res = self.portal_catalog(portal_type = "Faculty")
1245            self._v_faculties = {}
1246            for f in res:
1247                self._v_faculties[f.getId] = f.getObject()
1248        f = self._v_faculties.get(fid,None)
1249        if f is None:
1250            return '', "No Faculty with ID: %s" % fid
1251        else:
1252            did = mapping.get('code')
1253            d = getattr(f,did,None)
1254            if d is None or d.portal_type == "Faculty":
[2267]1255                logger.info('Creating Department %(code)s, %(title)s' % mapping)
[2283]1256                try:
1257                    f.invokeFactory('Department', did)
1258                except BadRequest,E:
1259                    return '', "%s" % E
[2193]1260                d = getattr(f,did)
1261                d.invokeFactory('CoursesFolder','courses')
1262                courses = getattr(d,'courses')
1263                dict = {'Title': 'Courses'}
1264                courses.getContent().edit(mapping=dict)
1265                d.invokeFactory('CertificatesFolder','certificates')
1266                certificates = getattr(d,'certificates')
1267                dict = {'Title': 'Certificates'}
1268                certificates.getContent().edit(mapping=dict)
1269            d.getContent().edit(mapping=mapping)
1270        return did,''
1271    ###)
[1620]1272
[2234]1273    security.declareProtected(ModifyPortalContent,'mass_edit_department') ###(
[2193]1274    def mass_edit_department(self,mapping):
1275        "create a department in the correct faculty"
1276        logger = logging.getLogger('WAeUPTool.mass_create_department')
1277        academics_folder = self.portal_url.getPortalObject().campus.academics
1278        fid = mapping['faculty_code']
1279        did = mapping.get('code')
1280        try:
1281            d = getattr(getattr(academics_folder,fid),did,None)
1282        except KeyError:
1283            return '', "Department %s or Faculty %s wrong" % (did,fid)
1284        else:
1285            if d is None or d.portal_type == "Faculty":
[2267]1286                logger.info('Editing Department %(code)s, %(title)s' % mapping)
[2193]1287            d.getContent().edit(mapping=mapping)
1288        return did,''
1289    ###)
[1786]1290
[2265]1291    security.declareProtected(ModifyPortalContent,'mass_create_course') ###(
1292    def mass_create_course(self,mapping):
[2315]1293        #import pdb;pdb.set_trace()
[2265]1294        if getattr(self,'_v_course_list',None) is None:
1295            self._v_course_list = []
1296        if getattr(self,'_v_departments',None) is None:
1297            res = self.portal_catalog(portal_type = "Department")
[2313]1298            self._v_department_courses = {}
[2265]1299            for d in res:
[2313]1300                self._v_department_courses[d.getId] = getattr(d.getObject(),"courses",None)
[2265]1301        did = mapping['department_code']
[2313]1302        d = self._v_department_courses.get(did,None)
[2265]1303        if d is None:
[2282]1304            return '', "No Department with ID: %s" % did
[2265]1305        course_id = mapping.get('code')
1306        if course_id in self._v_course_list:
[2313]1307            return '', "Duplicate Course ID: %s" % did
[2265]1308        c = getattr(d,course_id,None)
1309        if c is not None:
[2313]1310            return '', "Duplicate Course ID: %s" % did
[2283]1311        try:
1312            d.invokeFactory('Course', course_id)
1313        except BadRequest,E:
1314            return '', "%s" % E
[2265]1315        self._v_course_list.append(course_id)
1316        c = getattr(d,course_id)
1317        c.getContent().edit(mapping=mapping)
1318        return course_id,''
1319    ###)
1320
[2282]1321    security.declareProtected(ModifyPortalContent,'mass_edit_course') ###(
1322    def mass_edit_course(self,mapping):
1323        #import pdb;pdb.set_trace()
1324        course_id = mapping.get('code')
1325        res = self.portal_catalog(id=course_id)
1326        if not res:
[2289]1327            return '', "No Course with ID: %s" % course_id
[2282]1328        c = res[0].getObject()
1329        c.getContent().edit(mapping=mapping)
1330        return course_id,''
1331    ###)
1332
1333    security.declareProtected(ModifyPortalContent,'mass_create_certificate') ###(
1334    def mass_create_certificate(self,mapping):
1335        if getattr(self,'_v_certificate_list',None) is None:
1336            self._v_certificate_list = []
[2313]1337        if getattr(self,'_v_department_certificates',None) is None:
[2282]1338            res = self.portal_catalog(portal_type = "Department")
[2313]1339            self._v_department_certificates = {}
[2282]1340            for d in res:
[2313]1341                self._v_department_certificates[d.getId] = getattr(d.getObject(),"certificates",None)
[2282]1342        did = mapping['department_code']
[2313]1343        d = self._v_department_certificates.get(did,None)
[2282]1344        if d is None:
1345            return '', "No Department with ID: %s" % did
1346        certificate_id = mapping.get('code')
1347        if certificate_id in self._v_certificate_list:
[2313]1348            return '', "Duplicate Certificate ID: %s" % did
[2282]1349        c = getattr(d,certificate_id,None)
1350        if c is not None:
[2313]1351            return '', "Duplicate Certificate ID: %s" % did
[2283]1352        try:
1353            d.invokeFactory('Certificate', certificate_id)
1354        except BadRequest,E:
1355            return '', "%s" % E
[2282]1356        self._v_certificate_list.append(certificate_id)
1357        c = getattr(d,certificate_id)
1358        c.getContent().edit(mapping=mapping)
1359        return certificate_id,''
1360    ###)
1361
1362    security.declareProtected(ModifyPortalContent,'mass_edit_certificate') ###(
1363    def mass_edit_certificate(self,mapping):
1364        #import pdb;pdb.set_trace()
1365        certificate_id = mapping.get('code')
1366        res = self.portal_catalog(id=certificate_id)
1367        if not res:
1368            return '', "No Certificate with ID: %s" % did
1369        c = res[0].getObject()
1370        c.getContent().edit(mapping=mapping)
1371        return certificate_id,''
1372    ###)
1373
[2520]1374    security.declareProtected(ModifyPortalContent,'mass_create_application') ###(
1375    def mass_create_application(self,mapping):
[2514]1376        #import pdb;pdb.set_trace()
[2547]1377        reg_no = mapping.get('reg_no')
[2514]1378        try:
1379            self.applicants_catalog.addRecord(**mapping)
1380        except ValueError:
[2548]1381            return '', "applicant record with reg_no %s already exists" % reg_no
[2546]1382        return reg_no,''
[2514]1383    ###)
1384
[2520]1385    security.declareProtected(ModifyPortalContent,'mass_edit_application') ###(
1386    def mass_edit_application(self,mapping):
[2514]1387        #import pdb;pdb.set_trace()
1388        reg_no = mapping.get('reg_no')
1389        try:
1390            self.applicants_catalog.modifyRecord(**mapping)
1391        except KeyError:
[2548]1392            return '', "applicant record with reg_no %s does not exist" % reg_no
[2514]1393        return reg_no,''
1394    ###)
1395
[2501]1396    security.declareProtected(ModifyPortalContent,'mass_create_course_result') ###(
1397    def mass_create_course_result(self,mapping):
[2500]1398        #import pdb;pdb.set_trace()
[2501]1399        if getattr(self,'_v_courses',None) is None:
1400            res = self.courses_catalog()
1401            self._v_courses = {}
1402            for brain in res:
[2520]1403                self._v_courses[brain.code] = brain
[2500]1404        course_id = mapping.get('code')
[2501]1405        if course_id not in self._v_courses.keys():
1406            return '', "No course with ID: %s" % did
1407        id_key = ''
1408        for id_key in ('student_id','matric_no'):
1409            id_field = mapping.get(id_key,None)
1410            if id_field is not None:
1411                student_id = id_field
1412                break
1413        query = Eq(id_key,id_field)
1414        res = self.students_catalog.evalAdvancedQuery(query)
1415        if not res:
1416            return '', "No student with %(id_field)s: %(id_key)s" % vars()
1417        if id_field != "student_id":
1418            mapping['student_id'] = res[0].id
1419        mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % mapping
1420        for k in ('semester',):
1421            mapping[k] = getattr(self._v_courses[course_id],k)
[2500]1422        try:
[2501]1423            self.course_results.addRecord(**mapping)
1424        except ValueError:
1425            return '', "course result already exists: %s" % key
1426        return key,''
[2500]1427    ###)
1428
1429    security.declareProtected(ModifyPortalContent,'mass_edit_course_result') ###(
1430    def mass_edit_course_result(self,mapping):
1431        #import pdb;pdb.set_trace()
1432        # if getattr(self,'_v_courses',None) is None:
1433        #     res = self.courses_catalog()
1434        #     self._v_courses = {}
1435        #     for brain in res:
[2520]1436        #         self._v_courses[brain.code] = brain
[2500]1437        # course_id = mapping.get('code')
1438        # if course_id not in self._v_courses.keys():
1439        #     return '', "No course with ID: %s" % did
1440        id_key = ''
1441        for id_key in ('student_id','matric_no'):
1442            id_field = mapping.get(id_key,None)
1443            if id_field is not None:
1444                student_id = id_field
1445                break
1446        query = Eq(id_key,id_field)
1447        res = self.students_catalog.evalAdvancedQuery(query)
1448        if not res:
1449            return '', "No student with %(id_field)s: %(id_key)s" % vars()
1450        if id_field != "student_id":
1451            mapping['student_id'] = res[0].id
1452        mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % mapping
1453        # for k in ('semester',):
1454        #     mapping[k] = getattr(self._v_courses[course_id],k)
1455        try:
1456            self.course_results.modifyRecord(**mapping)
1457        except KeyError:
1458            return '', "No course result to edit: %s" % key
1459        return key,''
1460    ###)
1461
[2282]1462    security.declareProtected(ModifyPortalContent,'mass_create_certificate_course') ###(
1463    def mass_create_certificate_course(self,mapping):
[2320]1464        if getattr(self,'_v_courses',None) is None:
1465            res = self.courses_catalog()
[2351]1466            self._v_courses= [course.code for course in res]
[2282]1467        if getattr(self,'_v_ceritficates',None) is None:
1468            res = self.portal_catalog(portal_type = "Certificate")
1469            self._v_certificates = {}
1470            for cert in res:
1471                self._v_certificates[cert.getId] = cert.getObject()
[2284]1472        certificate_course_id = mapping.get('code')
[2351]1473        if certificate_course_id not in self._v_courses:
[2284]1474            return '', "No Course with ID: %s" % certificate_course_id
[2282]1475        cert_id = mapping['certificate_code']
1476        cert = self._v_certificates.get(cert_id,None)
1477        if cert is None:
[2284]1478            return '', "No Certificate with ID: %s" % cert_id
[2282]1479        level_id = mapping.get('level')
1480        level = getattr(cert,level_id,None)
1481        if level is None:
1482            cert.invokeFactory('StudyLevel', level_id)
1483            level = getattr(cert,level_id,None)
1484        elif hasattr(level,certificate_course_id):
1485            return '', "Duplicate CertificateCourse ID: %s in %s/ %s" %\
1486            (certificate_course_id,cert_id,level_id)
1487        level.invokeFactory('CertificateCourse', certificate_course_id)
1488        c = getattr(level,certificate_course_id)
1489        c.getContent().edit(mapping=mapping)
1490        return certificate_course_id,''
1491    ###)
1492
[2193]1493    field2types_student = {   ###(
[1756]1494                      'StudentApplication':
1495                          {'id': 'application',
1496                           'title': 'Application Data',
[1991]1497                           'wf_transition_return': 'close',
1498                           'wf_transition_admit': 'remain',
[1756]1499                           'fields':
1500                             ('jamb_reg_no',
1501                              'entry_mode',
1502                              'entry_session',
1503                              'jamb_score',
[1786]1504                              'app_email',
[2008]1505                              'jamb_age',
[2428]1506                              'jamb_state',
1507                              'jamb_lga',
[1756]1508                              )
1509                              },
[1786]1510                      #'StudentPume':
1511                      #    {'id': 'pume',
1512                      #     'title': 'Pume Data',
[1991]1513                      #     'wf_transition_return': 'close',
1514                      #     'wf_transition_admit': 'close',
[1786]1515                      #     'fields':
1516                      #       ('pume_score',
1517                      #        )
1518                      #        },
[1756]1519                      'StudentClearance':
1520                          {'id': 'clearance',
[2009]1521                           'title': 'Clearance/Eligibility Record',
[1991]1522                           'wf_transition_return': 'close',
1523                           'wf_transition_admit': 'remain',
[1756]1524                           'fields':
1525                             ('matric_no',
1526                              'nationality',
1527                              'lga',
[1804]1528                              'birthday',
[1756]1529                              )
1530                              },
1531                         'StudentPersonal':
1532                          {'id': 'personal',
1533                           'title': 'Personal Data',
[1991]1534                           'wf_transition_return': 'open',
1535                           'wf_transition_admit': 'remain',
[1756]1536                           'fields':
1537                             ('firstname',
1538                              'middlename',
1539                              'lastname',
1540                              'sex',
1541                              'email',
1542                              'phone',
1543                              'perm_address',
1544                              )
1545                              },
1546                         'StudentStudyCourse':
1547                          {'id': 'study_course',
1548                           'title': 'Study Course',
[1991]1549                           'wf_transition_return': 'open',
1550                           'wf_transition_admit': 'remain',
[1756]1551                           'fields':
1552                             ('study_course',
1553                              'current_level',
1554                              'current_session',
1555                              'current_mode',
1556                              'current_verdict',
[2478]1557                              'previous_verdict',
[1756]1558                              )
1559                              },
[1898]1560
1561                         'PaymentsFolder':
1562                          {'id': 'payments',
1563                           'title': 'Payments',
[1991]1564                           'wf_transition_return': 'open',
1565                           'wf_transition_admit': 'open',
[1898]1566                           'fields':
1567                             ()
1568                              },
[1756]1569                         }
1570    ###)
1571
[2193]1572    security.declareProtected(ModifyPortalContent,'mass_create_student') ###(
1573    def mass_create_student(self,mapping):
[1781]1574        "create a students record due import"
[2193]1575        logger = logging.getLogger('WAeUPTool.mass_create_student')
[1747]1576        students_folder = self.portal_url.getPortalObject().campus.students
[1818]1577        jamb_reg_no = mapping.get('jamb_reg_no',None)
[1747]1578        if jamb_reg_no:
1579            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1580            if res:
[1749]1581                return '',"jamb_reg_no exists"
[1818]1582        matric_no = mapping.get('matric_no',None)
[1747]1583        if matric_no:
1584            res = self.students_catalog(matric_no = matric_no)
1585            if res:
[1749]1586                return '',"matric_no exists"
[1747]1587        sid = self.waeup_tool.generateStudentId('?')
1588        students_folder.invokeFactory('Student', sid)
1589        student_obj = getattr(students_folder,sid)
[2193]1590        f2t = self.field2types_student
[1772]1591        d = {}
[1990]1592        transition = mapping.get('reg_transition','admit')
1593        if transition not in ('admit','return'):
[2008]1594            return '',"no valid transition provided"
[1747]1595        for pt in f2t.keys():
1596            student_obj.invokeFactory(pt,f2t[pt]['id'])
1597            sub_obj = getattr(student_obj,f2t[pt]['id'])
1598            sub_doc = sub_obj.getContent()
[1772]1599            d['Title'] = f2t[pt]['title']
[1747]1600            for field in f2t[pt]['fields']:
[1818]1601                d[field] = mapping.get(field,'')
[2454]1602
1603            if pt == "StudentApplication":
[2436]1604                d['jamb_sex']  = 'M'
1605                if mapping.get('sex'):
1606                    d['jamb_sex']  = 'F'
1607                d['jamb_firstname'] = mapping.get('firstname',None)
1608                d['jamb_middlename'] = mapping.get('middlename',None)
1609                d['jamb_lastname'] = mapping.get('lastname',None)
1610
[2433]1611            # if pt == "StudyCourse":
1612            #     for von,zu in (('entry_mode','current_mode'),
1613            #                    ('entry_session','current_session')):
1614            #         if mapping.get(zu,None) is None and mapping.get(von,None) is not None:
1615            #             d[zu] = mapping[von]
[1747]1616            sub_doc.edit(mapping = d)
[1990]1617
[1987]1618            #import pdb;pdb.set_trace()
1619            new_state = f2t[pt]['wf_transition_%(transition)s' % vars()]
[1898]1620            if new_state != "remain":
1621                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
[1990]1622        self.portal_workflow.doActionFor(student_obj,transition)
[1747]1623        student_obj.manage_setLocalRoles(sid, ['Owner',])
1624        return sid,''
1625    ###)
1626
[2193]1627    security.declareProtected(ModifyPortalContent,'mass_edit_student') ###(
1628    def mass_edit_student(self,mapping):
[1781]1629        "edit a students record due import"
[2193]1630        logger = logging.getLogger('WAeUPTool.mass_edit_student')
[1774]1631        students_folder = self.portal_url.getPortalObject().campus.students
[1818]1632        sid = mapping.get('id',None)
1633        jamb_reg_no = mapping.get('jamb_reg_no',None)
1634        matric_no = mapping.get('matric_no',None)
[1875]1635        editable_keys = mapping.keys()
[1774]1636        if sid:
1637            res = self.students_catalog(id = sid)
1638            if not res:
1639                return '',"no student with id %s" % sid
[2268]1640            if matric_no and res[0].matric_no and\
[1774]1641              matric_no != res[0].matric_no:
[2268]1642                logger.info("%s, old matric_no %s overwritten with %s" % (res[0].id,res[0].matric_no,matric_no))
1643            if jamb_reg_no and res[0].jamb_reg_no and\
[1774]1644              jamb_reg_no != res[0].jamb_reg_no:
[2268]1645                logger.info("%s, old reg_no %s overwritten with %s" % (res[0].id,res[0].jamb_reg_no,jamb_reg_no))
[1844]1646        elif jamb_reg_no:
1647            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1648            if not res:
1649                return '',"no student with jamb_reg_no %s" % jamb_reg_no
[1875]1650            editable_keys.remove('jamb_reg_no')
[1774]1651        elif matric_no:
1652            res = self.students_catalog(matric_no = matric_no)
1653            if not res:
1654                return '',"no student with matric_no %s" % matric_no
[1875]1655            editable_keys.remove('matric_no')
[1965]1656
[2268]1657        ## included only to change wf state from admitted to returning
1658        #if res[0].review_state not in ('admitted','objection_raised'):
1659        #    return '%s' % res[0].id ,"student is not in state admitted or objection_raised"
1660        ## end inclusion
[1965]1661
[1774]1662        sid = res[0].id
1663        student_obj = getattr(students_folder,sid)
[2193]1664        f2t = self.field2types_student
[1774]1665        d = {}
[2265]1666        #import pdb;pdb.set_trace()
[1875]1667        any_change = False
[1774]1668        for pt in f2t.keys():
[1875]1669            if pt == "student_application":
1670                d['jamb_sex']  = 'M'
1671                if mapping.get('sex'):
1672                    d['jamb_sex']  = 'F'
1673            intersect = set(f2t[pt]['fields']).intersection(set(editable_keys))
1674            if intersect:
1675                sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1676                if sub_obj is None:
1677                    try:
1678                        student_obj.invokeFactory(pt,f2t[pt]['id'])
1679                    except:
1680                        continue
1681                    sub_obj = getattr(student_obj,f2t[pt]['id'])
1682                    d['Title'] = f2t[pt]['title']
1683                sub_doc = sub_obj.getContent()
1684                for field in intersect:
1685                    changed = False
[2478]1686                    if getattr(sub_doc,field,None) != mapping.get(field,''):
[1875]1687                        any_change = True
1688                        changed = True
1689                        d[field] = mapping.get(field,'')
1690                    if changed:
1691                        sub_doc.edit(mapping = d)
[1904]1692
[1905]1693
[2268]1694        ## included only to change wf state from admitted to returning
1695        #    if res[0].review_state in ('admitted','objection_raised'):
1696        #        new_state = f2t[pt]['wf_transition_return']
1697        #        sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1698        #        if sub_obj and new_state != "remain":
1699        #            try:
1700        #                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1701        #            except:
1702        #                #logger.info('%s, wf transition %s of %s failed' % (sid,new_state,sub_obj.id))
1703        #                pass
1704        #if res[0].review_state in ('admitted','objection_raised'):
1705        #    wfaction = 'return'
1706        #    try:
1707        #        self.portal_workflow.doActionFor(student_obj,wfaction)
1708        #        logger.info('%s, wf state changed' % sid)
1709        #        any_change = True
1710        #    except:
1711        #        logger.info('%s, wf transition failed, old state = %s' % (sid,res[0].review_state))
1712        #        pass
1713        ## end inclusion
[1904]1714
[1905]1715
[1875]1716        if any_change:
1717            return sid,''
1718        else:
1719            return sid,'not modified'
[1774]1720    ###)
[1905]1721
[1730]1722    security.declareProtected(ModifyPortalContent,"importData")###(
[2259]1723    def importData(self,filename,name,edit=False,bypass_queue_catalog=False):
[1730]1724        """load data from CSV values"""
1725        import transaction
1726        import random
[1775]1727
[1773]1728        pm = self.portal_membership
[1775]1729        member = pm.getAuthenticatedMember()
1730
[1747]1731        logger = logging.getLogger('WAeUPTool.importData')
[1730]1732        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1733        students_folder = self.portal_url.getPortalObject().campus.students
1734        start = True
[2495]1735        tr_count = 0
[1756]1736        total_imported = 0
1737        total_not_imported = 0
[1730]1738        total = 0
[1749]1739        iname = "import_%s" % name
[2528]1740        if iname == 'import_application':
1741            commit_after = 2000
1742        else:
1743            commit_after = 100
[1747]1744        stool = getToolByName(self, 'portal_schemas')
1745        ltool = getToolByName(self, 'portal_layouts')
1746        schema = stool._getOb(iname)
[1730]1747        if schema is None:
[1772]1748            em = 'No such schema %s' % iname
1749            logger.error('No such schema %s' % iname)
[1756]1750            return em
[1747]1751        layout = ltool._getOb(iname)
[1730]1752        if layout is None:
[1772]1753            em = 'No such layout %s' % iname
[1756]1754            logger.error(em)
1755            return em
[1730]1756        validators = {}
1757        for widget in layout.keys():
[1749]1758            validators[widget] = layout[widget].validate
[2193]1759        #import pdb;pdb.set_trace()
[2289]1760        mode = "create"
[1774]1761        if edit:
[2289]1762            mode = "edit"
1763        importer_name = "mass_%(mode)s_%(name)s" % vars()
[1772]1764        importer = getattr(self, '%s' % importer_name,None)
1765        if importer is None:
1766            em = 'No importer function %s' % importer_name
[1756]1767            logger.error(em)
1768            return em
[1747]1769        not_imported = []
[1730]1770        imported = []
1771        try:
[1747]1772            items = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
[1730]1773        except:
[1756]1774            em = 'Error reading %s.csv' % filename
1775            logger.error(em)
1776            return em
[1730]1777        for item in items:
1778            if start:
1779                start = False
[1747]1780                adapters = [MappingStorageAdapter(schema, item)]
[2315]1781                logger.info('%s starts import from %s.csv in %s mode with schema and layout %s' % (member,filename,mode,iname))
[2094]1782                attrs = csv.reader(open("%s/import/%s.csv" % (i_home,filename),"rb")).next()
1783                import_keys = [k for k in attrs if not k.startswith('ignore')]
[1804]1784                diff2schema = set(import_keys).difference(set(schema.keys()))
1785                diff2layout = set(import_keys).difference(set(layout.keys()))
1786                if diff2schema:
[2282]1787                    em = 'not ignorable key(s): "%s" found in heading' % ", ".join(diff2schema)
[1804]1788                    return em
[2433]1789                if mode == "create":
[2436]1790                    required_keys = [layout.getIdUnprefixed(id)
[2433]1791                                     for id,widget in layout.objectItems()
1792                                     if widget.is_required]
1793                    if not set(required_keys).issubset(set(import_keys)):
1794                        diff2import = set(required_keys).difference(set(import_keys))
1795                        em = 'required key(s): "%s" not found in heading' % ", ".join(diff2import)
1796                        return em
[1753]1797                s = ','.join(['"%s"' % fn for fn in import_keys])
[1772]1798                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(s + ',"Error"'+ '\n')
1799                s = '"id",' + s
[1756]1800                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
[1730]1801                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
1802                format_error = format + ',"%(Error)s"'
[1756]1803                format = '"%(id)s",'+ format
[2267]1804
[2094]1805            dm = DataModel(item, adapters,context=self)
[1747]1806            ds = DataStructure(data=item,datamodel=dm)
1807            error_string = ""
[2495]1808            total += 1
[1730]1809            for k in import_keys:
[2289]1810                if not validators[k](ds,mode=mode):
[2264]1811                    error_string += " %s : %s" % (k,
1812                                                  self.translation_service(ds.getError(k),
1813                                                                           ds.getErrorMapping(k)))
[1747]1814            if not error_string:
[2433]1815                temp_item = item.copy()
1816                temp_item.update(dm)
[2435]1817                temp_item['id'],error = importer(temp_item)
[1747]1818                if error:
1819                    error_string += error
[2433]1820                else:
1821                    item = temp_item
[2436]1822            if error_string:
[1747]1823                item['Error'] = error_string
1824                not_imported.append(format_error % item)
[1756]1825                total_not_imported += 1
[1747]1826            else:
[1821]1827                em = format % item
1828                imported.append(em)
[1875]1829                tr_count += 1
[1756]1830                total_imported += 1
[2495]1831                logger.info("%(total_imported)d of %(total)d %(em)s" % vars())
[2520]1832
[2528]1833            if total and not total % commit_after:
[1875]1834                transaction.commit()
[1747]1835                if len(not_imported) > 0:
1836                    open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1837                             '\n'.join(not_imported) + '\n')
1838                    not_imported = []
1839                if len(imported) > 0:
1840                    open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
[1772]1841                             '\n'.join(imported) + '\n')
[1747]1842                    imported = []
[1730]1843                em = '%d transactions committed\n' % (tr_count)
1844                regs = []
1845                logger.info(em)
1846                tr_count = 0
[2528]1847                #if total > 100:
1848                #    return
[1756]1849        if len(imported) > 0:
[1747]1850            open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
1851                                                '\n'.join(imported))
[1756]1852        if len(not_imported) > 0:
[1747]1853            open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
1854                                                '\n'.join(not_imported))
[2496]1855        em = "Finished: %d imported, %d not imported (of total %d)" % (total_imported,total_not_imported,total)
[2495]1856        logger.info(em)
[1756]1857        return em
[1730]1858    ###)
1859
[2292]1860    security.declareProtected(ModifyPortalContent,"moveImagesToFS")###(
1861    def moveImagesToFS(self,student_id="O738726"):
1862        "move the images to the filesystem"
[2675]1863        images_dir = getImagesDir(student_id)
1864        #images_dir = os.path.join("%s" % images_base,student_id)
[2292]1865        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1866        stool = getToolByName(self, 'portal_schemas')
1867        schemas = ['student_application',
1868                   'student_clearance',
1869                   ]
1870        created = False
1871        for schema_id in schemas:
1872            schema = stool._getOb(schema_id)
1873            object = getattr(student_folder,schema_id[len('student_'):],None)
1874            if object is None:
1875                continue
1876            doc = object.getContent()
1877            for key in schema.keys():
1878                if schema[key].meta_type != "CPS Image Field":
1879                    continue
1880                #import pdb;pdb.set_trace()
[2351]1881                image = getattr(doc,key,None)
1882                if not image or not hasattr(image,"data"):
[2292]1883                    continue
1884                if not created:
1885                    if not os.path.exists(images_dir):
1886                        os.mkdir(images_dir)
1887                    created = True
1888                filename = os.path.join(images_dir,"%(key)s_%(student_id)s.jpg" % vars())
1889                open(filename,"wb").write(str(image.data))
[2500]1890    ###)
[2292]1891
[2300]1892    security.declareProtected(ModifyPortalContent,"movePassportToFS")###(
1893    def movePassportToFS(self,student_id="O738726"):
1894        "move the passports to the filesystem"
1895        images_dir = os.path.join("%s" % i_home,'passports')
1896        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1897        stool = getToolByName(self, 'portal_schemas')
1898        schemas = ['student_application',
1899                   #'student_clearance',
1900                   ]
1901        created = False
1902        for schema_id in schemas:
1903            schema = stool._getOb(schema_id)
1904            object = getattr(student_folder,schema_id[len('student_'):],None)
1905            if object is None:
1906                continue
1907            doc = object.getContent()
1908            for key in schema.keys():
1909                if schema[key].meta_type != "CPS Image Field":
1910                    continue
1911                #import pdb;pdb.set_trace()
1912                image = getattr(doc,key)
1913                if not hasattr(image,"data"):
1914                    continue
1915                if not created:
1916                    if not os.path.exists(images_dir):
1917                        os.mkdir(images_dir)
1918                    created = True
1919                filename = os.path.join(images_dir,"%(student_id)s.jpg" % vars())
1920                open(filename,"wb").write(str(image.data))
[2500]1921    ###)
[2300]1922
[828]1923InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.