source: WAeUP_SRP/base/WAeUPTool.py @ 3163

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

fix for #477

  • Property svn:keywords set to Id
File size: 106.8 KB
Line 
1#-*- mode: python; mode: fold -*-
2# (C) Copyright 2005 The WAeUP group  <http://www.waeup.org>
3# Author: Joachim Schmitz (js@aixtraware.de)
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License version 2 as published
7# by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software
16# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17# 02111-1307, USA.
18#
19# $Id: WAeUPTool.py 3162 2008-02-14 08:04:50Z joachim $
20"""The WAeUP Tool Box.
21"""
22
23from AccessControl import ClassSecurityInfo
24from Acquisition import aq_inner
25from Acquisition import aq_parent
26from Globals import DTMLFile
27from Globals import InitializeClass
28from OFS.SimpleItem import SimpleItem
29from zExceptions import BadRequest
30
31from Products.CMFCore.utils import getToolByName
32from Products.CPSSchemas.DataStructure import DataStructure
33from Products.CPSSchemas.DataModel import DataModel
34from Products.CPSSchemas.StorageAdapter import MappingStorageAdapter
35from Products.CMFCore.ActionProviderBase import ActionProviderBase
36from Products.CMFCore.permissions import View
37from Products.ZCatalog.ZCatalog import ZCatalog
38from Products.CMFCore.permissions import ModifyPortalContent
39from Products.CMFCore.permissions import ManagePortal
40from Products.CMFCore.utils import UniqueObject
41from Products.CMFCore.URLTool import URLTool
42from Products.CMFCore.utils import getToolByName
43from Students import makeCertificateCode
44from Globals import package_home,INSTANCE_HOME
45import DateTime,time
46import logging
47import transaction
48import csv,re,os,sys
49from shutil import copy2
50from Products.AdvancedQuery import Eq, Between, Le,In
51
52p_home = package_home(globals())
53i_home = INSTANCE_HOME
54images_base = os.path.join(i_home,"images")
55
56def getImagesDir(student_id):
57    return os.path.join("%s" % images_base,student_id[0],student_id)
58
59def getObject(object,name):
60    if object.hasObject(name):
61        return getattr(object,name)
62    return None
63
64
65class WAeUPTool(UniqueObject, SimpleItem, ActionProviderBase):
66    """WAeUP tool"""
67
68    id = 'waeup_tool'
69    meta_type = 'WAeUP Tool'
70    _actions = ()
71    security = ClassSecurityInfo()
72    security.declareObjectProtected(View)
73    manage_options = ( ActionProviderBase.manage_options
74                     + SimpleItem.manage_options
75                     )
76
77    security.declareProtected(View,'re_split') ###(
78    def re_split(self,split_string,string):
79        return re.split(split_string,string)
80    ###)
81
82    security.declareProtected(View,'difference') ###(
83    def difference(self,l1,l2):
84        return set(l1).difference(set(l2))
85    ###)
86
87    def rwrite(self,s): ###(
88        response = self.REQUEST.RESPONSE
89        response.setHeader('Content-type','text/html; charset=ISO-8859-15')
90        response.write("%s<br />\r\n" % s)
91    ###)
92
93    def addtodict(self,d,key,item): ###(
94        d[key].append(item)
95        return d[key]
96    ###)
97
98    def sleep(self,secs): ###(
99        "sleep"
100        import time
101        time.sleep(secs)
102        return
103
104###)
105
106    security.declareProtected(View,'updateRoleMappingsFor') ###(
107    def updateRoleMappingsFor(self,wf_definition,ob):
108        "do so for public"
109        wf_def = getattr(self.portal_workflow,wf_definition)
110        wf_def.updateRoleMappingsFor(ob)
111    ###)
112
113    security.declareProtected(View,'getStatesLgas') ###(
114    def getStatesLgas(self):
115        """return lga info"""
116        voc = getattr(self.portal_vocabularies,'local_gov_areas')
117        states = []
118        lgas  = []
119        d = {}
120        wd = {}
121        for k,v in voc.items():
122            parts = v.split(' / ')
123            if len(parts) == 1:
124                state = parts[0].lower()
125                lga = ""
126            elif len(parts) == 2:
127                state = "_".join(re.split('[^a-zA-Z0-9/]',parts[0].lower()))
128                lga = "-".join(re.split('[^a-zA-Z0-9/]',parts[1].lower()))
129            else:
130                continue
131            if state not in states:
132                states.append(state)
133            if lga not in lgas:
134                lgas.append(lga)
135            words = re.split('[^a-zA-Z0-9/]',k)
136            words.sort()
137            wd[k] = words
138            d[k] = v
139        mapping = {}
140        mapping['word_dict'] = wd
141        mapping['lga_dict'] = d
142        mapping['states'] = states
143        mapping['lgas'] = lgas
144        return mapping
145    ###)
146
147    security.declareProtected(View,'findLga') ###(
148    def findLga(self,words,words_dict):
149        words = re.split('[^a-zA-Z0-9/]',words)
150        lga_words = []
151        for word in words:
152            if word:
153                lga_words += word.strip().lower(),
154        lga_words.sort()
155        state_lga = ''
156        while not state_lga:
157            for k,l in words_dict.items():
158                if lga_words == l:
159                    state_lga = k
160                    break
161            break
162        return state_lga
163    ###)
164    security.declareProtected(View,'getAccessInfo') ###(
165    def getAccessInfo(self,context):
166        "return a dict with access_info"
167        logger = logging.getLogger('WAeUPTool.getAccessInfo')
168        mtool = self.portal_membership
169        member = mtool.getAuthenticatedMember()
170        member_id = str(member)
171        info = {}
172        is_anonymous = info['is_anonymous'] = mtool.isAnonymousUser()
173        is_student = info['is_student'] = ord(member_id[1]) > 48 and ord(member_id[1]) <= 57
174        is_staff = info['is_staff'] = not is_anonymous and not is_student
175        roles = member.getRolesInContext(context)
176        is_sectionofficer = info['is_sectionofficer'] = not is_student and ("SectionOfficer" in roles or
177                                                                            "SectionManager" in roles or
178                                                                            "Manager" in roles)
179        is_allowed = info['is_allowed'] = not is_anonymous
180        requested_id = context.getStudentId()
181        student_id  = None
182        if is_allowed:
183            if not is_student and requested_id:
184                student_id  = requested_id
185            elif is_anonymous or member_id != requested_id:
186                logger.info('%s tried to access %s of %s' % (member_id,context.portal_type,requested_id))
187            else:
188                student_id = member_id
189        info['student_id'] = student_id
190        return info
191    ###)
192
193    security.declareProtected(ModifyPortalContent,'openLog') ###(
194    def openLog(self,name):
195        """open a log file"""
196        version = 1
197        path = "%s/log/%s_%d.log" % (i_home,name,version)
198        while os.path.exists(path):
199            version += 1
200            path = "%s/log/%s_%d.log" % (i_home,name,version)
201        log = open(path,"w")
202        return log
203    ###)
204
205    security.declareProtected(ModifyPortalContent,'bypassQueueCatalog') ###(
206    def bypassQueueCatalog(self,enable=True):
207        """bypass the QueueCatalog by setting all indexes to process imediate,
208        if enable is True (default) the old settings are restored
209        """
210
211    ###)
212
213    security.declareProtected(ModifyPortalContent,'measureOaT') ###(
214    def measureOaT(self,method="a",probe="1000",nr_pts="1"):
215        """measure Object access Time"""
216        import random
217        if hasattr(self,'portal_catalog_real'):
218            aq_portal = self.portal_catalog_real.evalAdvancedQuery
219        else:
220            aq_portal = self.portal_catalog.evalAdvancedQuery
221        nr_pts = int(nr_pts)
222        probe = int(probe)
223        intervall = probe/10
224        objects = ("application","clearance","personal")
225        portal_types = ("StudentApplication","StudentClearance","StudentPersonal")
226        #i = random.randrange(num_objects)
227        count = 0
228        found = 0
229        not_found = 0
230        t_found = 0
231        t_not_found = 0
232        time_found = time_not_found = 0.0
233        t_time_found = t_time_not_found = 0.0
234        accessed = []
235        t_min = 1000
236        t_max = 0
237        #import pdb;pdb.set_trace()
238        students = self.portal_catalog(portal_type="Student")
239        num_students = len(students)
240        if method == "d":
241            query = Eq('path','/uniben/campus/students') & In('portal_type',portal_types[:nr_pts])
242            res = aq_portal(query)
243            brains = {}
244            for r in res:
245                sid = r.relative_path.split('/')[-2]
246                if brains.has_key(sid):
247                    brains[sid][r.portal_type] = r
248                else:
249                    brains[sid] = {r.portal_type : r}
250            brains_list = brains.keys()
251            num_objects = len(brains_list)
252        else:
253            num_objects = num_students
254        print "="*40
255        print "method: %s probes: %d nr_pts: %d num_objects: %d" % (method,
256                                                                        probe,
257                                                                        nr_pts,
258                                                                        num_objects)
259        print "nr found/not time found/not min/max"
260        elapse = time.time()
261        i_elapse = time.time()
262        c_elapse = time.clock()
263        for c in range(1,probe + 1):
264            i = random.randrange(num_objects)
265            if method in ('a','b','c'):
266                student_brain = students[i]
267            elif method == "d":
268                #import pdb;pdb.set_trace()
269                student_brain = brains[brains_list[i]]
270            if method == "c":
271                query = Eq('path',student_brain.getPath()) & In('portal_type',portal_types[:nr_pts])
272                res = aq_portal(query)
273                this_portal_types = [r.portal_type for r in res]
274            for i in range(nr_pts):
275                oid = objects[i]
276                if method == "a":
277                    try:
278                        student_path = student_brain.getPath()
279                        path = "%s/%s" % (student_path,oid)
280                        doc = self.unrestrictedTraverse(path).getContent()
281                        found += 1
282                        i_time = time.time() - i_elapse
283                        time_found += i_time
284                    except:
285                        not_found += 1
286                        i_time = time.time() - i_elapse
287                        time_not_found += i_time
288                        pass
289                elif method == "b":
290                    try:
291                        student_object = student_brain.getObject()
292                        doc = getattr(student_object,oid).getContent()
293                        found += 1
294                        i_time = time.time() - i_elapse
295                        time_found += i_time
296                    except:
297                        i_time = time.time() - i_elapse
298                        time_not_found += i_time
299                        not_found += 1
300                        pass
301                elif method == "c":
302                    if portal_types[i] in this_portal_types:
303                        found += 1
304                        doc = res[this_portal_types.index(portal_types[i])].getObject().getContent()
305                        i_time = time.time() - i_elapse
306                        time_found += i_time
307                    else:
308                        not_found += 1
309                        i_time = time.time() - i_elapse
310                        time_not_found += i_time
311                elif method == "d":
312                    if student_brain.has_key(portal_types[i]):
313                        found += 1
314                        doc = student_brain[portal_types[i]].getObject().getContent()
315                        i_time = time.time() - i_elapse
316                        time_found += i_time
317                    else:
318                        not_found += 1
319                        i_time = time.time() - i_elapse
320                        time_not_found += i_time
321                i_elapse = time.time()
322            if c and (c % intervall == 0):
323                #i_time = time.time() - i_elapse
324                t_per = 0.0
325                if found:
326                    t_per = time_found/found
327                if t_per > t_max:
328                    t_max = t_per
329                if t_per > 0.0 and t_per < t_min:
330                    t_min = t_per
331                itf = 0.0
332                if found:
333                    itf = time_found/found
334                itnf = 0.0
335                if not_found :
336                    itnf = time_not_found / not_found
337                interval_time = time_found + time_not_found
338                s = "%(c)d: %(found)d/%(not_found)d " % vars()
339                s += "%(interval_time)6.2f %(itf)6.4f/%(itnf)6.4f " % vars()
340                s += "%(t_min)6.4f/%(t_max)6.4f" %  vars()
341                print s
342                t_found += found
343                t_not_found += not_found
344                t_time_found += time_found
345                t_time_not_found += time_not_found
346                time_found = time_not_found = 0.0
347                found = not_found = 0
348        # t_found += found
349        # t_not_found += not_found
350        elapse = time.time() - elapse
351        itf = 0.0
352        if t_found:
353            itf = t_time_found/t_found
354        itnf = 0.0
355        if t_not_found:
356            itnf = t_time_not_found / t_not_found
357        #c_elapse = time.clock() - c_elapse
358        s = "%(probe)d: %(t_found)d/%(t_not_found)d " % vars()
359        s += "%(elapse)6.2f %(itf)6.4f/%(itnf)6.4f " % vars()
360        s += "%(t_min)6.4f/%(t_max)6.4f" %  vars()
361        print "-"*40
362        print s
363        rel_found = float(t_found)/probe
364        rel_not_found = float(t_not_found)/probe
365        estimated_total_time = num_objects*(rel_found*itf + rel_not_found*itnf)
366        print estimated_total_time
367    ###)
368
369    security.declareProtected(ModifyPortalContent,'writeLog') ###(
370    def writeLog(self,logfile,s):
371        """write to the log file"""
372        logfile.write(s)
373
374###)
375
376    def generateStudentId(self,letter): ###(
377        import random
378        r = random
379        ##if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
380        if letter == '?':
381            letter= r.choice('ABCDEFGHKLMNPQRSTUVWXY')
382        sid = "%c%d" % (letter,r.randint(99999,1000000))
383        students = self.portal_url.getPortalObject().campus.students
384##        while hasattr(students, sid):
385##            sid = "%c%d" % (letter,r.randint(99999,1000000))
386        while self.students_catalog(id = sid):
387            sid = "%c%d" % (letter,r.randint(99999,1000000))
388        return sid
389    ###)
390
391    def generatePassword(self,s=None): ###(
392        import random
393        r = random
394        ##if letter not in ('ABCDEFGIHKLMNOPQRSTUVWXY'):
395        if s is None:
396            s = 'abcdefghklmnpqrstuvwxy23456789'
397        pw = ''
398        while len(pw) < 6:
399            pw += r.choice(s)
400        return pw
401    ###)
402
403    security.declareProtected(ModifyPortalContent, 'dumpSchoolfeePayments') ###(
404    def dumpSchoolfeePayments(self):
405        "dump paid schoolfees"
406        mtool = self.portal_membership
407        member = mtool.getAuthenticatedMember()
408        logger = logging.getLogger('WAeUPTool.dumpSchoolfees')
409        aq_student = self.students_catalog.evalAdvancedQuery
410        query = In('review_state',('schoolfee_paid',
411                                   'courses_registered',
412                                   'courses_validated',
413                                   ))
414        res = aq_student(query)
415        #import pdb;pdb.set_trace()
416        l = []
417        logger.info("start for %d" % len(res))
418        count = 1
419        log_after = 100
420        for student in res:
421            if not count % log_after:
422                logger.info("processed %d total %d" % (log_after,count))
423            count += 1
424            fee_dict =self.getSchoolFee(student)
425            fulltime = student.mode.endswith('_ft')
426            d = {}
427            d['student_id'] = student.id
428            d['name'] = student.name
429            d['amount'] = fee_dict.get(new_returning)
430            l += d,
431        csv_name = self.dumpListToCSV(l,'payments')
432        logger.info('%s dumped payments to %s' % (member,export_file))
433    ###)
434
435    security.declarePublic('dumpListToCSV') ###(
436    def dumpListToCSV(self,l,filename,fields=None):
437        """dump a list of dicts to a CSV file"""
438        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
439        export_file = "%s/export/%s_%s.csv" % (i_home,filename,current,)
440        if fields is None:
441            fields = l[0].keys()
442        headline = ','.join(fields)
443        out = open(export_file,"wb")
444        out.write(headline +'\n')
445        out.close()
446        out = open(export_file,"a")
447        csv_writer = csv.DictWriter(out,fields,)
448        csv_writer.writerows(l)
449        return export_file
450    ###)
451
452    security.declareProtected(ManagePortal, 'listMembers') ###(
453    def listMembers(self):
454        "list all members"
455        mtool = self.portal_membership
456        member = mtool.getAuthenticatedMember()
457        logger = logging.getLogger('WAeUPTool.listMembers')
458        if str(member) not in ('admin','joachim'):
459            logger.info('%s tried to list members' % (member))
460            return None
461        members = self.portal_directories.members
462        all = members.listEntryIdsAndTitles()
463        l = []
464        for user_id,name in all:
465            d = {}
466            d['user_id'] = user_id
467            d['name'] = name
468            d['pw'] = getattr(getattr(members,user_id),'password')
469            d['email'] = getattr(getattr(members,user_id),'email')
470            d['groups'] = " ".join(getattr(getattr(members,user_id),'groups'))
471            d['roles'] = " ".join(getattr(getattr(members,user_id),'roles'))
472            l += d,
473        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
474        export_file = "%s/export/member_list_%s.csv" % (i_home,current,)
475        logger.info('%s dumped memberlist to %s' % (member,export_file))
476        fields = l[0].keys()
477        headline = ','.join(fields)
478        out = open(export_file,"wb")
479        out.write(headline +'\n')
480        out.close()
481        out = open(export_file,"a")
482        csv_writer = csv.DictWriter(out,fields,)
483        csv_writer.writerows(l)
484    ###)
485
486    security.declareProtected(ManagePortal, 'removeDeletedDocIds') ###(
487    def removeDeletedDocIds(self, max=1000):
488        """
489        remove deleted docids from repository commit after max
490        """
491        logger = logging.getLogger('WAeUPTool.removeDeletedDocIds')
492        repository = getToolByName(self, 'portal_repository')
493        pxtool = getToolByName(self, 'portal_proxies')
494        logger.info('start')
495        pxtool_infos = pxtool.getRevisionsUsed()
496        logger.info('found  %d used revisions ' % (len(pxtool_infos)))
497
498        nb_revs = 0
499        docids_d = {} # all docids
500        unused_docids_d = {} # all docids that are unused
501        ids_unused_revs_docids = [] # ids for revs of unused docids
502        unused_ids = [] # ids for unused revs
503        total = 0
504        idlist = repository.objectIds()
505        to_delete = 0
506        found = False
507        for id in idlist:
508            docid, rev = repository._splitId(id)
509            if docid is None:
510                logger.info("invalid doc_id %s" % docid)
511                continue
512            nb_revs += 1
513            if not pxtool_infos.has_key(docid):
514                found = True
515                to_delete += 1
516                unused_ids.append(id)
517            elif not pxtool_infos[docid].has_key(rev):
518                found = True
519                to_delete += 1
520                unused_ids.append(id)
521            if found and not to_delete % max:
522                found = False
523                #import pdb;pdb.set_trace()
524                repository.manage_delObjects(unused_ids)
525                transaction.commit()
526                logger.info('removed %d total %d unused docids ' % (max,to_delete))
527        else:
528            if unused_ids:
529                repository.manage_delObjects(unused_ids)
530                transaction.commit()
531        logger.info('finished removing %d unused docids ' % (to_delete))
532
533
534###)
535
536    security.declareProtected(View,'getCredential') ###(
537    def getCredential(self,student_id):
538        student_entry = getattr(self.portal_directories.students,student_id,None)
539        if not self.isStaff():
540            mtool = self.portal_membership
541            member = mtool.getAuthenticatedMember()
542            logger = logging.getLogger('WAeUPTool.getCredential')
543            logger.info('%s tried to access password of %s' % (member,student_id))
544            return None
545        if student_entry is None:
546            return None
547        return getattr(student_entry,"password","not set")
548    ###)
549
550    security.declarePublic('checkPassword') ###(
551    def checkPassword(self,student_id,password):
552        student_entry = getattr(self.portal_directories.students,student_id,None)
553        if student_entry is None:
554            return False
555        return getattr(student_entry,"password","not set") == password
556    ###)
557
558    security.declarePublic('checkGenericPassword') ###(
559    def checkGenericPassword(self,member_id):
560        member_entry = getattr(self.portal_directories.members,member_id,None)
561        if member_entry is None:
562            return False
563        ltool = getToolByName(self, 'portal_layouts')
564        unsecure_words = ltool._getOb('members')['w__password'].check_words
565        password = getattr(member_entry,"password","not set")
566        is_unsecure = password in unsecure_words
567        if is_unsecure:
568            logger = logging.getLogger('WAeUPTool.checkGenericPassword')
569            logger.info('Member %s tried to log in with unsecure password %s' %(member_id,password))
570        return is_unsecure
571    ###)
572
573    security.declareProtected(ModifyPortalContent,'editPassword') ###(
574    def editPassword(self,student_id,password):
575        "edit a student password"
576        student_entry = getattr(self.portal_directories.students,student_id,None)
577        if student_entry is None:
578            return
579        setattr(student_entry,'password',password)
580    ###)
581
582    security.declareProtected(ModifyPortalContent,'doCommit') ###(
583    def doCommit(self,logger=None):
584        "commit some transactions"
585        transaction.commit()
586    ###)
587
588    security.declarePublic('loadStudentFoto') ###(
589    def loadStudentFoto(self,student,filename,folder):
590        "return a student passport picture"
591        #import pdb;pdb.set_trace()
592        picture ="%s/import/%s/%s" % (i_home,folder,filename)
593        student_id = student.getId()
594        images_dir = getImagesDir(student_id)
595        if not os.path.exists(images_dir):
596            os.mkdir(images_dir)
597        image_name = os.path.join(images_dir,"passport_%(student_id)s.jpg" % vars())
598        for extension in ('.jpg','.JPG'):
599            fullname = "%(picture)s%(extension)s" % vars()
600            if os.path.exists(fullname):
601                copy2(fullname,image_name)
602                return "successfully copied passport picture"
603        return "passport picture not found: %s.jpg or .JPG" % picture
604    ###)
605
606    def old____loadStudentFoto(self,student,filename,folder): ###(
607        "return a student passport picture"
608        app = student.application
609        app_doc = app.getContent()
610        #clear = student.clearance
611        #clear_doc = clear.getContent()
612        #matric_no = clear_doc.matric_no.upper()
613        picture1 ="%s/import/%s/%s.jpg" % (i_home,folder,filename)
614        picture2 ="%s/import/%s/%s.JPG" % (i_home,folder,filename)
615        #import pdb;pdb.set_trace()
616        if os.path.exists(picture1):
617            file = open(picture1)
618        elif os.path.exists(picture2):
619            file = open(picture2)
620        else:
621            return "passport picture not found %s" % picture1
622        reopened = False
623        if self.portal_workflow.getInfoFor(app,'review_state',None) !='opened':
624            self.portal_workflow.doActionFor(app,'open')
625            reopened = True
626        outfile = file.read()
627        app_doc.manage_addFile('passport',
628                               file=outfile,
629                               title="%s.jpg" % filename)
630        if reopened:
631            self.portal_workflow.doActionFor(app,'close')
632        return "successfully loaded passport picture"
633    ###)
634
635    security.declareProtected(ModifyPortalContent,'createOne') ###(
636    def createOne(self,students_folder,student_brain,letter,commit=False):
637        sid = self.waeup_tool.generateStudentId(letter)
638        students_folder.invokeFactory('Student', sid)
639        student = getattr(students_folder,sid)
640        self.portal_workflow.doActionFor(student,'return')
641        student.manage_setLocalRoles(sid, ['Owner',])
642        matric_no = student_brain.matric_no
643        jamb_reg_no = student_brain.Entryregno
644        self.students_catalog.addRecord(id = sid,
645                                           matric_no = matric_no,
646                                           jamb_reg_no = jamb_reg_no,
647                                           sex = student_brain.Sex == "F",
648                                           name = "%s %s %s" % (student_brain.Firstname,
649                                                                student_brain.Middlename,
650                                                                student_brain.Lastname)
651                                        )
652        if commit:
653            transaction.commit()
654        return sid,jamb_reg_no
655    ###)
656
657    security.declareProtected(ModifyPortalContent,'addStudent') ###(
658    def addStudent(self,dict):
659        students_folder = self.portal_url.getPortalObject().campus.students
660        sid = self.waeup_tool.generateStudentId('?')
661        students_folder.invokeFactory('Student', sid)
662        student_obj = getattr(students_folder,sid)
663        f2t = self.field2types_student
664        #from pdb import set_trace; set_trace()
665        d = {}
666        #d['jamb_sex']  = 'M'
667        #if dict.get('sex'):
668        #    d['jamb_sex']  = 'F'
669
670        entry_session = dict.get('entry_session')
671        if entry_session == self.getSessionId()[0]:
672            wfaction = 'admit'
673            wft = 'wf_transition_admit'
674            password = None
675        else:
676            wfaction = 'return'
677            wft = 'wf_transition_return'
678            password = self.generatePassword()
679            self.makeStudentMember(sid,password)
680
681        for pt in f2t.keys():
682            student_obj.invokeFactory(pt,f2t[pt]['id'])
683            sub_obj = getattr(student_obj,f2t[pt]['id'])
684            sub_doc = sub_obj.getContent()
685            #self.portal_workflow.doActionFor(sub_obj,'open',dest_container=sub_obj)
686            d['Title'] = f2t[pt]['title']
687            for field in f2t[pt]['fields']:
688                d[field] = dict.get(field,'')
689            sub_doc.edit(mapping = d)
690            new_state = f2t[pt][wft]
691            if new_state != "remain":
692                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
693        self.portal_workflow.doActionFor(student_obj,wfaction)
694        student_obj.manage_setLocalRoles(sid, ['Owner',])
695        return sid,password
696    ###)
697
698    security.declarePublic('getCertificateBrain') ###(
699    def getCertificateBrain(self,cert_id):
700        "do it"
701        res = ZCatalog.searchResults(self.portal_catalog_real,
702                                {'portal_type':"Certificate",
703                                      'id': cert_id})
704        if res:
705            return res[0]
706        return None
707    ###)
708
709    security.declareProtected(ModifyPortalContent,'get_csv_filenames') ###(
710    def get_csv_filenames(self):
711        "do it"
712        files = [file for file in os.listdir("%s/import/" % (i_home))
713                 if file.endswith('.csv') and (file.find('imported') == -1 and
714                                               file.find('pending') == -1)]
715        return files
716    ###)
717
718    security.declarePublic('findStudentByMatricelNo') ###(
719    def findStudentByMatricelNo(self,matric_no):
720        "do it"
721        res = ZCatalog.searchResults(self.portal_catalog_real,
722                                {'portal_type':"StudentClearance",
723                                 'SearchableText': matric_no})
724        if res:
725            return res[0]
726        return None
727    ###)
728
729    security.declarePublic('makeStudentMember') ###(
730    def makeStudentMember(self,sid,password='uNsEt'):
731        """make the student a member"""
732        membership = self.portal_membership
733        membership.addMember(sid,
734                             password ,
735                             roles=('Member',
736                                     'Student',
737                                     ),
738                             domains='',
739                             properties = {'memberareaCreationFlag': False,
740                                           'homeless': True},)
741        member = membership.getMemberById(sid)
742        self.portal_registration.afterAdd(member, sid, password, None)
743        #self.manage_setLocalRoles(sid, ['Owner',])
744    ###)
745
746    security.declareProtected(View,'makeStudentData') ###(
747    def makeStudentData(self,student_id,email=None,phone_nr=None):
748        "create Datastructure for a returning Student"
749        #import pdb;pdb.set_trace()
750        logger = logging.getLogger('WAeUPTool.makeStudentData')
751        students_folder = self.portal_url.getPortalObject().campus.students
752        #res = self.students_catalog(id=student_id)
753        #if res:
754        #    st = res[0]
755        #res = self.returning_import(matric_no = st.matric_no)
756        res = self.returning_import(id = student_id)
757        if res:
758            student = res[0]
759        else:
760            logger.info('Id %s not found in returning_import' % student_id)
761            return
762        logger.info('%s creates data structure' % student_id)
763        s_results = self.results_import(matric_no = student.matric_no)
764        if s_results:
765            lnr = self.getLevelFromResultsCosCode(s_results)
766            level = "%d00" % lnr
767            verdict,eligible = self.getVerdict(s_results[0].Verdict)
768            #if eligible:
769            #    level = "%d00" % (lnr + 1)
770        else:
771            logger.info('matric_no %s not found in results_import' % student.matric_no)
772            level = ''
773            verdict = ''
774        #student should not be allowed to perform this transition
775        #wftool = self.portal_workflow
776        #wftool.doActionFor(student,'return')
777        certcode_org = student.Coursemajorcode
778        certcode = makeCertificateCode(certcode_org)
779        certificate_brain = self.getCertificateBrain(certcode)
780        if not certificate_brain:
781            em = 'Certificate %s org-code %s not found\n' % (certcode, certcode_org)
782            logger.info(em)
783        matric_no = student.matric_no
784        sid = student_id
785        student_obj = getattr(students_folder,sid)
786        if not getattr(student_obj,'application'):
787            student_obj.invokeFactory('StudentApplication','application')
788        application = student_obj.application
789        self.portal_workflow.doActionFor(application,'open',dest_container=application)
790        da = {'Title': 'Application Data'}
791        student_obj.invokeFactory('StudentPersonal','personal')
792        da['jamb_reg_no'] = student.Entryregno
793        em = self.getEntryMode(student.Entryregno)
794        da['entry_mode'] = em
795        personal = student_obj.personal
796        self.portal_workflow.doActionFor(personal,'open',dest_container=personal)
797        dp = {'Title': 'Personal Data'}
798        student_obj.invokeFactory('StudentClearance','clearance')
799        clearance = student_obj.clearance
800        self.portal_workflow.doActionFor(clearance,'open',dest_container=clearance)
801        dc = {'Title': 'Clearance/Eligibility Record'}
802        dc['matric_no'] = matric_no
803        state = student.State
804        lga = student.LGA
805        if state and lga:
806            lga =  state + ' / ' + lga
807        else:
808            lga = "None"
809        da['jamb_lga'] = dc['lga'] = lga
810        da['app_email'] = dp['email'] = email
811        da['app_mobile'] = dp['phone'] = phone_nr
812        dp['firstname'] = student.Firstname
813        dp['middlename'] = student.Middlename
814        dp['lastname'] = student.Lastname
815        da['jamb_lastname'] = "%s %s %s" % (student.Firstname,student.Middlename,student.Lastname)
816        da['jamb_sex'] = student.Sex
817        dp['sex'] = student.Sex == 'F'
818        dp['perm_address'] = student.Permanent_Address
819        application.getContent().edit(mapping=da)
820        self.portal_workflow.doActionFor(application,'close',dest_container=application)
821        personal.getContent().edit(mapping=dp)
822        clearance.getContent().edit(mapping=dc)
823        self.portal_workflow.doActionFor(clearance,'close',dest_container=clearance)
824        #
825        # Study Course
826        #
827        student_obj.invokeFactory('StudentStudyCourse','study_course')
828        studycourse = student_obj.study_course
829        self.portal_workflow.doActionFor(studycourse,'open',dest_container=studycourse)
830        dsc = {}
831        dsc['study_course'] = certcode
832        dsc['current_level'] = level
833        dsc['current_verdict'] = verdict
834        dsc['current_mode'] = em
835        dsc['current_session'] = '05'
836        studycourse.getContent().edit(mapping=dsc)
837        #
838        # Level
839        #
840##        l = getattr(studycourse,level,None)
841##        if l is None:
842##            studycourse.invokeFactory('StudentStudyLevel', level)
843##            l = getattr(studycourse, level)
844##            self.portal_workflow.doActionFor(l,'open',dest_container=l)
845##            l.getContent().edit(mapping={'Title': "Level %s" % level})
846###)
847
848    security.declareProtected(ModifyPortalContent,'admitOneStudent') ###(
849    def admitOneStudent(self,brain,entry_session,pin_password):
850        "create Datastructure for an admitted Student"
851        #import pdb;pdb.set_trace()
852        if not hasattr(self,"_v_certificates"):
853            self._v_certificates = [entry[0] for entry in self.getCertificatesVoc()]
854        students_folder = self.portal_url.getPortalObject().campus.students
855        logger = logging.getLogger('WAeUPTool.admitOneStudent')
856        if brain.status != "admitted":
857            logger.info('status of %s is %s' % (brain.reg_no,brain.status))
858            return
859        pin_parts = brain.pin.split('-')
860        if pin_parts and len(pin_parts) != 3:
861            logger.info('invalid pin %s for %s' % (brain.pin,brain.reg_no))
862            return
863        if brain.course_admitted not in self._v_certificates:
864            logger.info('certificate %s not found for %s' % (brain.course_admitted,brain.reg_no))
865            return
866        if brain.sex not in (True,False):
867            logger.info('sex of %s not available' % (brain.reg_no))
868            return
869        student_id = self.generateStudentId('?')
870        students_folder.invokeFactory('Student', student_id)
871        student_object = getattr(students_folder,student_id)
872        if pin_password:
873            password = pin_parts[2]
874            self.makeStudentMember(student_id,password = password)
875        student_object.manage_setLocalRoles(student_id, ['Owner',])
876        #logger.info("creating %s reg_no %s" % (student_id,brain.reg_no))
877        #
878        # application
879        #
880        student_object.invokeFactory('StudentApplication','application')
881        application = student_object.application
882        #self.portal_workflow.doActionFor(application,'open',dest_container=application)
883        da = {'Title': 'Application Data'}
884        da['jamb_reg_no'] = brain.reg_no
885
886        sex = 'M'
887        if brain.sex:
888            sex = 'F'
889        da['jamb_sex'] = sex
890        da['jamb_age'] = brain.jamb_age
891        #da['app_ac_pin'] = brain.pin
892        da['jamb_lga'] = brain.jamb_lga
893        da['jamb_state'] = brain.jamb_state
894        da['jamb_score'] = brain.aggregate
895        da['app_email'] = brain.email
896        da['app_mobile'] = brain.phone
897        if brain.entry_mode:
898            da['entry_mode'] = brain.entry_mode
899        elif brain.screening_type == 'pume':
900            da['entry_mode'] = 'ume_ft'
901        elif brain.screening_type == 'pde':
902            da['entry_mode'] = 'de_ft'
903        elif brain.screening_type == 'pce':
904            da['entry_mode'] = 'pce'
905        elif brain.screening_type == 'prence':
906            da['entry_mode'] = 'prence'
907        else:
908            da['entry_mode'] = ''
909        da['entry_session'] = entry_session
910        da['jamb_lastname'] = brain.lastname
911        da['jamb_middlename'] = brain.middlenames   # different field names!
912        da['jamb_firstname'] = brain.firstname
913        da['screening_application_date'] = brain.application_date
914        da['date_of_birth'] = brain.date_of_birth
915        da['jamb_first_cos'] = brain.course1
916        da['jamb_second_cos'] = brain.course2
917        da['course3'] = brain.course3
918        da['screening_type'] = brain.screening_type
919        da['screening_score'] = brain.screening_score
920        da['screening_date'] = brain.screening_date
921        da['hq_type'] = brain.hq_type
922        da['hq_grade'] = brain.hq_grade
923        da['aos'] = brain.aos
924
925        application.getContent().edit(mapping=da)
926        #self.portal_workflow.doActionFor(application,'close',dest_container=application)
927        #
928        # personal
929        #
930        student_object.invokeFactory('StudentPersonal','personal')
931        personal = student_object.personal
932        #self.portal_workflow.doActionFor(personal,'open',dest_container=personal)
933        dp = {'Title': 'Personal Data'}
934        dp['sex'] = brain.sex
935        dp['email'] = brain.email
936        dp['phone'] = brain.phone
937        dp['lastname'] = brain.lastname
938        dp['middlename'] = brain.middlenames   # different field names!
939        dp['firstname'] = brain.firstname
940        personal.getContent().edit(mapping=dp)
941        #
942        # clearance
943        #
944        student_object.invokeFactory('StudentClearance','clearance')
945        clearance = student_object.clearance
946        #self.portal_workflow.doActionFor(clearance,'open',dest_container=clearance)
947        dc = {'Title': 'Clearance/Eligibility Record'}
948        dc['lga'] = brain.lga
949        dc['birthday'] = brain.date_of_birth
950        clearance.getContent().edit(mapping=dc)
951        #self.portal_workflow.doActionFor(clearance,'close',dest_container=clearance)
952        #
953        # study Course
954        #
955        student_object.invokeFactory('StudentStudyCourse','study_course')
956        studycourse = student_object.study_course
957        #self.portal_workflow.doActionFor(studycourse,'open',dest_container=studycourse)
958        dsc = {}
959        dsc['study_course'] = brain.course_admitted
960        dsc['current_verdict'] = ''
961        dsc['current_mode'] = da['entry_mode']
962        if da['entry_mode'].startswith('de'):
963            dsc['current_level'] = '200'
964        elif da['entry_mode'].startswith('pre'):
965            dsc['current_level'] = '000'
966        else:
967            dsc['current_level'] = '100'
968        dsc['current_session'] = entry_session
969        studycourse.getContent().edit(mapping=dsc)
970        #
971        # payments folder
972        student_object.invokeFactory('PaymentsFolder','payments')
973        payments = getattr(student_object,'payments')
974        dpay = {}
975        dpay['Title'] = 'Payments'
976        payments.getContent().edit(mapping=dpay)
977        self.portal_workflow.doActionFor(payments,'open')
978        #
979        # passport foto
980        app_picture ="%s/import/images/%s/%s_passport.jpg" % (i_home,
981                                                              brain.screening_type,
982                                                              brain.reg_no)
983        images_dir = getImagesDir(student_id)
984        #images_dir = os.path.join("%s" % images_base,student_id)
985        letter_dir,student_dir = os.path.split(images_dir)
986        if not os.path.exists(letter_dir):
987            os.mkdir(letter_dir)
988        if not os.path.exists(images_dir):
989            os.mkdir(images_dir)
990        image_name = os.path.join(images_dir,"passport_%(student_id)s.jpg" % vars())
991        if os.path.exists(app_picture):
992            copy2(app_picture,image_name)
993        else:
994            logger.info('passport of %s/%s not found: %s' % (student_id,
995                                                             brain.reg_no,
996                                                             app_picture))
997
998        return student_id
999    ###)
1000
1001    security.declareProtected(ModifyPortalContent,'makeStudentLevel') ###(
1002    def makeStudentLevel(self,student_id):
1003        "create the StudyLevel for a returning Student"
1004        #import pdb;pdb.set_trace()
1005        logger = logging.getLogger('WAeUPTool.makeStudentLevel')
1006        students_folder = self.portal_url.getPortalObject().campus.students
1007        res = self.students_catalog(id=student_id)
1008        if res:
1009            st = res[0]
1010        course = st.course
1011        matric_no = st.matric_no
1012        level = st.level
1013        res = self.results_import(matric_no = matric_no)
1014        if res:
1015            results = res
1016        logger.info('%s creating Level %s' % (student_id,level))
1017        #
1018        # Level
1019        #
1020        student_obj = getattr(self.portal_url.getPortalObject().campus.students,student_id)
1021        studycourse = getattr(student_obj,"study_course",None)
1022        self.portal_workflow.doActionFor(studycourse,'close_for_edit',dest_container=studycourse)
1023        l = getattr(studycourse,level,None)
1024        if l is None:
1025            studycourse.invokeFactory('StudentStudyLevel', level)
1026            l = getattr(studycourse, level)
1027            self.portal_workflow.doActionFor(l,'open',dest_container=l)
1028            l.getContent().edit(mapping={'Title': "Level %s" % level})
1029        ###)
1030
1031    security.declarePublic('getHallInfo') ###(
1032    def getHallInfo(self,bed):
1033        """return Hall Info"""
1034        info = {}
1035        hall,block,room,letter = bed.split('_')
1036        res = ZCatalog.searchResults(self.portal_catalog_real,portal_type="AccoHall",id=hall)
1037        if res and len(res) == 1:
1038            hall_brain = res[0]
1039            hall_doc = hall_brain.getObject().getContent()
1040        else:
1041            return info
1042        info['hall_title'] = hall_brain.Title
1043        info['maintenance_code'] = hall_doc.maintenance_code
1044        res = ZCatalog.searchResults(self.portal_catalog_real,portal_type="ScratchCardBatch")
1045        batch_doc = None
1046        for brain in res:
1047            if brain.id.startswith(info['maintenance_code']):
1048                batch_doc = brain.getObject().getContent()
1049                break
1050        if batch_doc is None:
1051            info['maintenance_fee'] = ''
1052        else:
1053            info['maintenance_fee'] = batch_doc.cost
1054        return info
1055    ###)
1056
1057    security.declareProtected(ModifyPortalContent,'removePictureFolder') ###(
1058    def removePictureFolder(self,student_id):
1059        """remove picture_folder by renaming it"""
1060        path = 'images'
1061        picture_path = os.path.join(i_home,path,student_id)
1062        if not os.path.exists(picture_path):
1063            return False
1064        os.rename(picture_path,picture_path + "_removed")
1065        return True
1066    ###)
1067
1068    security.declareProtected(ModifyPortalContent,'restorePictureFolder') ###(
1069    def restorePictureFolder(self,student_id):
1070        """restore picture_folder by renaming it"""
1071        path = 'images'
1072        picture_path = os.path.join(i_home,path,student_id)
1073        if not os.path.exists(picture_path + "_removed"):
1074            return False
1075        os.rename(picture_path + "_removed",picture_path)
1076        return True
1077    ###)
1078
1079    security.declarePublic('picturesExist') ###(
1080    def picturesExist(self, ids,student_id=None):
1081        """check if pictures exist in the filesystem"""
1082        if student_id is None:
1083            student_id = self.getStudentId()
1084        if student_id is None:
1085            return False
1086        picture_path = getImagesDir(student_id)
1087        #picture_path = os.path.join(images_base,student_id)
1088        if not os.path.exists(picture_path):
1089            return False
1090        pictures  = [picture[:picture.rfind('_')] for picture in os.listdir(picture_path)]
1091        return set(ids).issubset(set(pictures))
1092    ###)
1093
1094    security.declarePublic('picturesList') ###(
1095    def picturesList(self):
1096        """check if pictures exist in the filesystem"""
1097        path = 'images'
1098        student_id = self.getStudentId()
1099        #picture_path = os.path.join(i_home,path,student_id)
1100        picture_path = getImagesDir(student_id)
1101        if not os.path.exists(picture_path):
1102            return []
1103        return [picture[:picture.rfind('_')] for picture in os.listdir(picture_path)]
1104    ###)
1105
1106    security.declarePublic('showFsPicture') ###(
1107    def showFsPicture(self,path):
1108        """return a picture from the filesystem"""
1109        #picture_path = os.path.join(i_home,path)
1110        picture_path = os.path.join(images_base,path)
1111        response = self.REQUEST.RESPONSE
1112        #import pdb;pdb.set_trace()
1113        registry = getToolByName(self, 'mimetypes_registry')
1114        mimetype = str(registry.lookupExtension(path.lower()) or
1115                    registry.lookupExtension('file.bin'))
1116        if os.path.exists(picture_path):
1117            response.setHeader('Content-type',mimetype)
1118            return open(picture_path).read()
1119        picture_path = os.path.join(i_home,'import',path)
1120        if os.path.exists(picture_path):
1121            return open(picture_path).read()
1122    ###)
1123
1124    security.declareProtected(ModifyPortalContent,'deleteAllCourses') ###(
1125    def deleteAllCourses(self,department="All"):
1126        ''' delete the courses'''
1127        pm = self.portal_membership
1128        member = pm.getAuthenticatedMember()
1129
1130        if str(member) not in ("henrik","joachim"):
1131            return "not possible"
1132        if department == "All":
1133            res = self.portal_catalog({'meta_type': 'Department'})
1134        if len(res) < 1:
1135            return "No Departments found"
1136
1137        deleted = []
1138        for dep in res:
1139            cf = dep.getObject().courses
1140            if cf:
1141                cf.manage_delObjects(ids=cf.objectIds())
1142                deleted.append("deleted Courses in %s" % dep.getId)
1143        return "\r".join(deleted)
1144    ###)
1145
1146    security.declareProtected(ModifyPortalContent,'getLogfileLines') ###(
1147    def getLogfileLines(self,filename="event.log",numlines=20):
1148        """Get last NUMLINES lines of logfile FILENAME.
1149
1150        Return last lines' of a file in the instances logfile directory as
1151        a list. The number of returned lines equals `numlines' or less. If
1152        less than `numlines' lines are available, the whole file ist
1153        returned. If the file can not be opened or some other error
1154        occurs, empty list is returend.
1155        """
1156        result = []
1157        lines_hit = 0
1158
1159        # We only handle files in instances' log directory...
1160        logpath = os.path.join(i_home, "log")
1161        filename = str(os.path.abspath( os.path.join( logpath, filename )))
1162        if not filename.startswith( logpath ):
1163            # Attempt to access file outside log-dir...
1164            return []
1165
1166        try:
1167            fd = file( filename, "rb" )
1168        except IOError:
1169            return []
1170        if not fd:
1171            return []
1172
1173        if os.linesep == None:
1174            linesep = '\n'
1175        else:
1176            linesep = os.linesep
1177
1178        # Try to find 'numlines' times a lineseparator, searching from end
1179        # and moving to the beginning of file...
1180        fd.seek( 0, 2) # Move to end of file...
1181        while lines_hit < numlines:
1182            if fd.read(1) == linesep[-1]: # This moves filedescriptor
1183                                          # one step forward...
1184                lines_hit += 1
1185            try:
1186                fd.seek( -2, 1) # Go two bytes back from current pos...
1187            except IOError:
1188                # We cannot go back two bytes. Maybe the file is too small...
1189                break
1190        fd.seek(2,1)
1191
1192        # Read all lines from current position...
1193        result = fd.readlines()
1194        # Remove line endings...
1195        result = [x.strip() for x in result]
1196        fd.close()
1197        return result
1198    ###)
1199
1200    security.declareProtected(ModifyPortalContent,"getCallbacksFromLog")###(
1201    def getCallbacksFromLog(self,filename):
1202        """fix Online Payment Transactions from Z2.log entries"""
1203        import transaction
1204        import random
1205        from cgi import parse_qs
1206        from urlparse import urlparse
1207        #from pdb import set_trace
1208        wftool = self.portal_workflow
1209        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1210        students_folder = self.portal_url.getPortalObject().campus.students
1211        s = r'(?P<client_ip>\S+) - (?P<member_id>\S+) \['
1212        s += r'(?P<date>.*)\] "(?P<get>.*)" (?P<codes>\d+ \d+) "'
1213        s += r'(?P<intersw>.*)" "(?P<agent>.*)"'
1214        data = re.compile(s)
1215        start = True
1216        tr_count = 1
1217        total = 0
1218        #name = 'pume_results'
1219        #name = 'epaymentsuccessful_z2log2'
1220        name = filename
1221        no_import = []
1222        imported = []
1223        logger = logging.getLogger('WAeUPTool.getFailedTransactions')
1224        try:
1225            transactions = open("%s/import/%s" % (i_home,name),"rb").readlines()
1226        except:
1227            logger.error('Error reading %s' % name)
1228            return
1229        tas = []
1230        for line in transactions:
1231            dict = {}
1232            items = data.search(line)
1233            dict['idict'] = idict = items.groupdict()
1234            #print idict
1235            #from pdb import set_trace;set_trace()
1236            urlparsed = urlparse(idict['get'][4:])
1237            #print urlparsed
1238            path = urlparsed[2].split('/')
1239            dict['student_id'] = student_id = path[8]
1240            dict['payment_id'] = payment_id = path[10]
1241            dict['qs_dict'] = qs_dict = parse_qs(urlparsed[4])
1242            tas.append(dict)
1243            tr_count += 1
1244        return tas
1245    ###)
1246
1247    security.declareProtected(ModifyPortalContent,"importOnlinePaymentTransactions")###(
1248    def importOnlinePaymentTransactions(self):
1249        """load Online Payment Transactions from CSV values"""
1250        import transaction
1251        import random
1252        #from pdb import set_trace
1253        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
1254        opt = self.online_payments_import
1255        students_folder = self.portal_url.getPortalObject().campus.students
1256        start = True
1257        tr_count = 1
1258        total = 0
1259        #name = 'pume_results'
1260        name = 'OnlineTransactions'
1261        no_import = []
1262        imported = []
1263        logger = logging.getLogger('WAeUPTool.importOnlinePaymentTransactions')
1264        try:
1265            transactions = csv.DictReader(open("%s/import/%s.csv" % (i_home,name),"rb"))
1266        except:
1267            logger.error('Error reading %s.csv' % name)
1268            return
1269        for pay_transaction in transactions:
1270            if start:
1271                start = False
1272                logger.info('Start loading from %s.csv' % name)
1273                s = ','.join(['"%s"' % fn for fn in pay_transaction.keys()])
1274                no_import.append('%s,"Error"' % s)
1275                format = ','.join(['"%%(%s)s"' % fn for fn in pay_transaction.keys()])
1276                format_error = format + ',"%(Error)s"'
1277            data = {}
1278
1279            # format of the first file sent by Tayo
1280            #data['datetime'] = date = DateTime.DateTime(pay_transaction['Date'])
1281            #data['student_id'] = student_id = pay_transaction['Payer ID']
1282            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
1283            #data['response_code'] = response_code = pay_transaction['Resp Code']
1284            #data['amount'] = amount = pay_transaction['Amount']
1285
1286            # format of the second file sent by Tayo
1287            #data['datetime'] = date = 0
1288            #data['student_id'] = student_id = pay_transaction['Payer ID']
1289            #data['order_id'] = order_id = pay_transaction['Order ID (Tranx Ref)']
1290            #data['response_code'] = response_code = '00'
1291            #data['amount'] = amount = pay_transaction['Amount']
1292
1293            # format of the third file sent by Kehinde
1294            data['datetime'] = date = 0
1295            data['student_id'] = student_id = pay_transaction['customer_id']
1296            data['order_id'] = order_id = pay_transaction['merchant_reference']
1297            data['response_code'] = response_code = '00'
1298            data['amount'] = amount = pay_transaction['Amount']
1299
1300            dup = False
1301            if response_code == "12":
1302                continue
1303            try:
1304                opt.addRecord(**data)
1305            except ValueError:
1306                dup = True
1307            #from pdb import set_trace;set_trace()
1308            if dup:
1309                if response_code == "00":
1310                    try:
1311                        opt.modifyRecord(**data)
1312                    except:
1313                        logger.info("duplicate uid, order_id %(order_id)s, student_id %(student_id)s, response_code %(response_code)s" % data)
1314                        continue
1315                else:
1316                    pay_transaction['Error'] = "Duplicate order_id"
1317                    no_import.append( format_error % pay_transaction)
1318                    logger.info("duplicate order_id %(order_id)s for %(student_id)s %(response_code)s" % data)
1319                    continue
1320            tr_count += 1
1321            if tr_count > 1000:
1322                if len(no_import) > 0:
1323                    open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1324                             '\n'.join(no_import) + '\n')
1325                    no_import = []
1326                em = '%d transactions committed\n' % (tr_count)
1327                transaction.commit()
1328                regs = []
1329                logger.info(em)
1330                total += tr_count
1331                tr_count = 0
1332        open("%s/import/%s_not_imported%s.csv" % (i_home,name,current),"a").write(
1333                                                '\n'.join(no_import))
1334        return self.REQUEST.RESPONSE.redirect("%s" % self.REQUEST.get('URL1'))
1335    ###)
1336
1337    security.declareProtected(ModifyPortalContent,'mass_create_faculty') ###(
1338    def mass_create_faculty(self,mapping):
1339        "create a faculty"
1340        logger = logging.getLogger('WAeUPTool.mass_create_faculty')
1341        academics_folder = self.portal_url.getPortalObject().campus.academics
1342        fid = mapping['code']
1343        if getattr(academics_folder,fid,None) is not None:
1344            return '', "Faculty with ID: %s exists" % fid
1345        logger.info('Creating Faculty %(code)s, %(title)s' % mapping)
1346        try:
1347            academics_folder.invokeFactory('Faculty', fid)
1348        except BadRequest,E:
1349            return '', "%s" % E
1350        f = getattr(academics_folder,fid,None)
1351        f.getContent().edit(mapping=mapping)
1352        return fid,''
1353    ###)
1354
1355    security.declareProtected(ModifyPortalContent,'mass_edit_faculty') ###(
1356    def mass_edit_faculty(self,mapping):
1357        "edit a faculty"
1358        logger = logging.getLogger('WAeUPTool.mass_edit_faculty')
1359        academics_folder = self.portal_url.getPortalObject().campus.academics
1360        fid = mapping['code']
1361        f = getattr(academics_folder,fid,None)
1362        if f is None:
1363            return '', "Faculty with ID: %s does not exist" % fid
1364        logger.info('Editing Faculty %(code)s, %(title)s' % mapping)
1365        f.getContent().edit(mapping=mapping)
1366        return fid,''
1367    ###)
1368
1369    security.declareProtected(ModifyPortalContent,'mass_create_department') ###(
1370    def mass_create_department(self,mapping):
1371        "create a department in the correct faculty"
1372        logger = logging.getLogger('WAeUPTool.mass_create_department')
1373        fid = mapping['faculty_code']
1374        if getattr(self,'_v_faculties',None) is None:
1375            res = self.portal_catalog(portal_type = "Faculty")
1376            self._v_faculties = {}
1377            for f in res:
1378                self._v_faculties[f.getId] = f.getObject()
1379        f = self._v_faculties.get(fid,None)
1380        if f is None:
1381            return '', "No Faculty with ID: %s" % fid
1382        else:
1383            did = mapping.get('code')
1384            d = getattr(f,did,None)
1385            if d is None or d.portal_type == "Faculty":
1386                logger.info('Creating Department %(code)s, %(title)s' % mapping)
1387                try:
1388                    f.invokeFactory('Department', did)
1389                except BadRequest,E:
1390                    return '', "%s" % E
1391                d = getattr(f,did)
1392                d.invokeFactory('CoursesFolder','courses')
1393                courses = getattr(d,'courses')
1394                dict = {'Title': 'Courses'}
1395                courses.getContent().edit(mapping=dict)
1396                d.invokeFactory('CertificatesFolder','certificates')
1397                certificates = getattr(d,'certificates')
1398                dict = {'Title': 'Certificates'}
1399                certificates.getContent().edit(mapping=dict)
1400            d.getContent().edit(mapping=mapping)
1401        return did,''
1402    ###)
1403
1404    security.declareProtected(ModifyPortalContent,'mass_edit_department') ###(
1405    def mass_edit_department(self,mapping):
1406        "create a department in the correct faculty"
1407        logger = logging.getLogger('WAeUPTool.mass_create_department')
1408        academics_folder = self.portal_url.getPortalObject().campus.academics
1409        fid = mapping['faculty_code']
1410        did = mapping.get('code')
1411        try:
1412            d = getattr(getattr(academics_folder,fid),did,None)
1413        except KeyError:
1414            return '', "Department %s or Faculty %s wrong" % (did,fid)
1415        else:
1416            if d is None or d.portal_type == "Faculty":
1417                logger.info('Editing Department %(code)s, %(title)s' % mapping)
1418            d.getContent().edit(mapping=mapping)
1419        return did,''
1420    ###)
1421
1422    security.declareProtected(ModifyPortalContent,'mass_create_course') ###(
1423    def mass_create_course(self,mapping):
1424        #import pdb;pdb.set_trace()
1425        if getattr(self,'_v_course_list',None) is None:
1426            self._v_course_list = []
1427        if getattr(self,'_v_departments',None) is None:
1428            res = self.portal_catalog(portal_type = "Department")
1429            self._v_department_courses = {}
1430            for d in res:
1431                self._v_department_courses[d.getId] = getattr(d.getObject(),"courses",None)
1432        did = mapping['department_code']
1433        d = self._v_department_courses.get(did,None)
1434        if d is None:
1435            return '', "No Department with ID: %s" % did
1436        course_id = mapping.get('code')
1437        if course_id in self._v_course_list:
1438            return '', "Duplicate Course ID: %s" % did
1439        c = getattr(d,course_id,None)
1440        if c is not None:
1441            return '', "Duplicate Course ID: %s" % did
1442        try:
1443            d.invokeFactory('Course', course_id)
1444        except BadRequest,E:
1445            return '', "%s" % E
1446        self._v_course_list.append(course_id)
1447        c = getattr(d,course_id)
1448        c.getContent().edit(mapping=mapping)
1449        return course_id,''
1450    ###)
1451
1452    security.declareProtected(ModifyPortalContent,'mass_edit_course') ###(
1453    def mass_edit_course(self,mapping):
1454        #import pdb;pdb.set_trace()
1455        course_id = mapping.get('code')
1456        res = self.portal_catalog(id=course_id)
1457        if not res:
1458            return '', "No Course with ID: %s" % course_id
1459        c = res[0].getObject()
1460        c.getContent().edit(mapping=mapping)
1461        return course_id,''
1462    ###)
1463
1464    security.declareProtected(ModifyPortalContent,'mass_create_certificate') ###(
1465    def mass_create_certificate(self,mapping):
1466        if getattr(self,'_v_certificate_list',None) is None:
1467            self._v_certificate_list = []
1468        if getattr(self,'_v_department_certificates',None) is None:
1469            res = self.portal_catalog(portal_type = "Department")
1470            self._v_department_certificates = {}
1471            for d in res:
1472                self._v_department_certificates[d.getId] = getattr(d.getObject(),"certificates",None)
1473        did = mapping['department_code']
1474        d = self._v_department_certificates.get(did,None)
1475        if d is None:
1476            return '', "No Department with ID: %s" % did
1477        certificate_id = mapping.get('code')
1478        if certificate_id in self._v_certificate_list:
1479            return '', "Duplicate Certificate ID: %s" % did
1480        c = getattr(d,certificate_id,None)
1481        if c is not None:
1482            return '', "Duplicate Certificate ID: %s" % did
1483        try:
1484            d.invokeFactory('Certificate', certificate_id)
1485        except BadRequest,E:
1486            return '', "%s" % E
1487        self._v_certificate_list.append(certificate_id)
1488        c = getattr(d,certificate_id)
1489        c.getContent().edit(mapping=mapping)
1490        return certificate_id,''
1491    ###)
1492
1493    security.declareProtected(ModifyPortalContent,'mass_edit_certificate') ###(
1494    def mass_edit_certificate(self,mapping):
1495        #import pdb;pdb.set_trace()
1496        certificate_id = mapping.get('code')
1497        res = self.portal_catalog(id=certificate_id)
1498        if not res:
1499            return '', "No Certificate with ID: %s" % certificate_id
1500        c = res[0].getObject()
1501        c.getContent().edit(mapping=mapping)
1502        return certificate_id,''
1503    ###)
1504
1505    security.declareProtected(ModifyPortalContent,'mass_create_application') ###(
1506    def mass_create_application(self,mapping):
1507        #import pdb;pdb.set_trace()
1508        reg_no = mapping.get('reg_no')
1509        try:
1510            self.applicants_catalog.addRecord(**mapping)
1511        except ValueError:
1512            return '', "applicant record with reg_no %s already exists" % reg_no
1513        return reg_no,''
1514    ###)
1515
1516    security.declareProtected(ModifyPortalContent,'mass_edit_application') ###(
1517    def mass_edit_application(self,mapping):
1518        #import pdb;pdb.set_trace()
1519        reg_no = mapping.get('reg_no')
1520        status = mapping.get('status')
1521        res = self.applicants_catalog(reg_no = reg_no)
1522        if len(res):
1523            if res[0].status == 'created' and status != 'created':
1524                return '', "student object with id %s for %s already created, status cannot be changed" % (res[0].student_id, reg_no)
1525            elif status == 'created' and res[0].status != 'created':
1526                return '', "student object for %s has not yet been created, status cannot be set to 'created'" % (reg_no)
1527            else:
1528                self.applicants_catalog.modifyRecord(**mapping)
1529                return reg_no,''
1530        else:
1531            return '', "applicant record with reg_no %s does not exist" % reg_no
1532
1533    ###)
1534
1535    security.declareProtected(ModifyPortalContent,'mass_create_course_result') ###(
1536    def mass_create_course_result(self,mapping):
1537        #import pdb;pdb.set_trace()
1538        students_folder = self.portal_url.getPortalObject().campus.students
1539        if getattr(self,'_v_courses',None) is None:
1540            res = self.courses_catalog()
1541            self._v_courses = {}
1542            for brain in res:
1543                self._v_courses[brain.code] = brain
1544        if getattr(self,'_v_level_created',None) is None:
1545            self._v_level_created = []
1546        course_id = mapping.get('code')
1547        if course_id not in self._v_courses.keys():
1548            return '', "No course with ID: %s" % course_id
1549        id_key = ''
1550        for id_key in ('student_id','matric_no'):
1551            id_field = mapping.get(id_key,None)
1552            if id_field is not None:
1553                student_id = id_field
1554                break
1555        query = Eq(id_key,id_field)
1556        res = self.students_catalog.evalAdvancedQuery(query)
1557        if not res:
1558            return '', "no student with %(id_key)s %(id_field)s" % vars()
1559        student_rec = res[0]
1560        if id_field != "student_id":
1561            mapping['student_id'] = student_rec.id
1562        student_id = student_rec.id
1563        level_id = mapping['level_id']
1564        code = mapping['code']
1565        if student_id not in self._v_level_created:
1566            try:
1567                context = getattr(getattr(students_folder,
1568                                          "%(student_id)s" % vars()),
1569                                  'study_course')
1570            except:
1571                return '', "could not create level %(level_id)s for %(student_id)s" % vars()
1572            if level_id not in context.objectIds():
1573                context.invokeFactory('StudentStudyLevel',"%(level_id)s" % vars())
1574                level = getattr(context,"%(level_id)s" % vars())
1575                self.portal_workflow.doActionFor(level,'open')
1576                # the session string must not be copied into the level object
1577                current_verdict = getattr(student_rec,'current_verdict','')
1578                current_session = getattr(student_rec,'current_session','')
1579                if current_verdict and student_rec.current_level == level_id:
1580                    level.getContent().edit(mapping={'verdict': "%s" %
1581                                                     current_verdict,
1582                                                     'session': "%s" %
1583                                                     current_session,
1584                                                    })
1585                    self.portal_workflow.doActionFor(level,'close')
1586            self._v_level_created += student_id,
1587        mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % vars()
1588        for k in ('semester','credits',):
1589            mapping[k] = getattr(self._v_courses[course_id],k)
1590        try:
1591            self.course_results.addRecord(**mapping)
1592        except ValueError:
1593            return '', "course result already exists: %s" % key
1594        return key,''
1595    ###)
1596
1597    security.declareProtected(ModifyPortalContent,'mass_edit_course_result') ###(
1598    def mass_edit_course_result(self,mapping):
1599        #import pdb;pdb.set_trace()
1600        while True:
1601            result_id = mapping.get('id',None)
1602            if result_id is not None:
1603                mapping['key'] = key = result_id
1604                break
1605            for id_key in ('student_id','matric_no'):
1606                id_field = mapping.get(id_key,None)
1607                if id_field is not None:
1608                    student_id = id_field
1609                    break
1610            query = Eq(id_key,id_field)
1611            res = self.students_catalog.evalAdvancedQuery(query)
1612            if not res:
1613                return '', "No student with %(id_key)s %(id_field)s" % vars()
1614            if id_field == "matric_no":
1615                mapping['student_id'] = res[0].id
1616            elif id_field == "student_id":
1617                mapping['matric_no'] = res[0].matric_no
1618            if not res:
1619                return '', "No student with %(id_key)s %(id_field)s" % vars()
1620            student_rec = res[0]
1621            student_id = student_rec.id
1622            level_id = mapping['level_id']
1623            code = mapping['code']
1624            mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % vars()
1625            break
1626        try:
1627            self.course_results.modifyRecord(**mapping)
1628        except KeyError:
1629            return key, "No course result to edit: %s" % key,mapping
1630        return key,''
1631    ###)
1632
1633    security.declareProtected(ModifyPortalContent,'mass_delete_course_result') ###(
1634    def mass_delete_course_result(self,mapping):
1635        id_key = ''
1636        for id_key in ('student_id','matric_no'):
1637            id_field = mapping.get(id_key,None)
1638            if id_field is not None:
1639                student_id = id_field
1640                break
1641        query = Eq(id_key,id_field)
1642        res = self.students_catalog.evalAdvancedQuery(query)
1643        if not res:
1644            return '', "No student with %(id_field)s: %(id_key)s" % vars()
1645        if id_field != "student_id":
1646            mapping['student_id'] = res[0].id
1647        if not res:
1648            return '', "no student with %(id_key)s %(id_field)s" % vars()
1649        student_rec = res[0]
1650        student_id = student_rec.id
1651        level_id = mapping['level_id']
1652        code = mapping['code']
1653        key = "%(student_id)s|%(level_id)s|%(code)s" % vars()
1654        # for k in ('semester',):
1655        #     mapping[k] = getattr(self._v_courses[course_id],k)
1656        if self.course_results.getRecordByKey(key) is None:
1657            return '', "no course-result with %(key)s" % vars()
1658        self.course_results.deleteRecord(key)
1659        return key,''
1660    ###)
1661
1662    security.declareProtected(ModifyPortalContent,'mass_create_certificate_course') ###(
1663    def mass_create_certificate_course(self,mapping):
1664        if getattr(self,'_v_courses',None) is None:
1665            res = self.courses_catalog()
1666            self._v_courses= [course.code for course in res]
1667        if getattr(self,'_v_ceritficates',None) is None:
1668            res = self.portal_catalog(portal_type = "Certificate")
1669            self._v_certificates = {}
1670            for cert in res:
1671                self._v_certificates[cert.getId] = cert.getObject()
1672        certificate_course_id = mapping.get('code')
1673        if certificate_course_id not in self._v_courses:
1674            return '', "No Course with ID: %s" % certificate_course_id
1675        cert_id = mapping['certificate_code']
1676        cert = self._v_certificates.get(cert_id,None)
1677        if cert is None:
1678            return '', "No Certificate with ID: %s" % cert_id
1679        level_id = mapping.get('level')
1680        level = getattr(cert,level_id,None)
1681        if level is None:
1682            cert.invokeFactory('StudyLevel', level_id)
1683            level = getattr(cert,level_id,None)
1684        elif hasattr(level,certificate_course_id):
1685            return '', "Duplicate CertificateCourse ID: %s in %s/ %s" %\
1686            (certificate_course_id,cert_id,level_id)
1687        level.invokeFactory('CertificateCourse', certificate_course_id)
1688        c = getattr(level,certificate_course_id)
1689        c.getContent().edit(mapping=mapping)
1690        return certificate_course_id,''
1691    ###)
1692
1693    field2types_student = {   ###(
1694                      'StudentApplication':
1695                          {'id': 'application',
1696                           'title': 'Application Data',
1697                           'wf_transition_return': 'close',
1698                           'wf_transition_admit': 'remain',
1699                           'fields':
1700                             ('jamb_reg_no',
1701                              'entry_mode',
1702                              'entry_session',
1703                              'jamb_score',
1704                              'app_email',
1705                              'jamb_age',
1706                              'jamb_state',
1707                              'jamb_lga',
1708                              'jamb_sex',
1709                              )
1710                              },
1711                      #'StudentPume':
1712                      #    {'id': 'pume',
1713                      #     'title': 'Pume Data',
1714                      #     'wf_transition_return': 'close',
1715                      #     'wf_transition_admit': 'close',
1716                      #     'fields':
1717                      #       ('pume_score',
1718                      #        )
1719                      #        },
1720                      'StudentClearance':
1721                          {'id': 'clearance',
1722                           'title': 'Clearance/Eligibility Record',
1723                           'wf_transition_return': 'close',
1724                           'wf_transition_admit': 'remain',
1725                           'fields':
1726                             ('matric_no',
1727                              'nationality',
1728                              'lga',
1729                              'birthday',
1730                              )
1731                              },
1732                         'StudentPersonal':
1733                          {'id': 'personal',
1734                           'title': 'Personal Data',
1735                           'wf_transition_return': 'open',
1736                           'wf_transition_admit': 'remain',
1737                           'fields':
1738                             ('firstname',
1739                              'middlename',
1740                              'lastname',
1741                              'sex',
1742                              'email',
1743                              'phone',
1744                              'perm_address',
1745                              )
1746                              },
1747                         'StudentStudyCourse':
1748                          {'id': 'study_course',
1749                           'title': 'Study Course',
1750                           'wf_transition_return': 'open',
1751                           'wf_transition_admit': 'remain',
1752                           'fields':
1753                             ('study_course',
1754                              'current_level',
1755                              'current_session',
1756                              'current_mode',
1757                              'current_verdict',
1758                              'previous_verdict',
1759                              )
1760                              },
1761                         # 'StudentStudyLevel':
1762                         #  {'id': 'current_level',
1763                         #   'title': '',
1764                         #   'wf_transition_return': 'open',
1765                         #   'wf_transition_admit': 'remain',
1766                         #   'fields':
1767                         #     ('verdict',
1768                         #      'session',
1769                         #      )
1770                         #      },
1771                         'PaymentsFolder':
1772                          {'id': 'payments',
1773                           'title': 'Payments',
1774                           'wf_transition_return': 'open',
1775                           'wf_transition_admit': 'open',
1776                           'fields':
1777                             ()
1778                              },
1779                         }
1780    ###)
1781
1782    security.declareProtected(ModifyPortalContent,'mass_create_student') ###(
1783    def mass_create_student(self,mapping):
1784        "create student records due import"
1785        logger = logging.getLogger('WAeUPTool.mass_create_student')
1786        students_folder = self.portal_url.getPortalObject().campus.students
1787        jamb_reg_no = mapping.get('jamb_reg_no',None)
1788        if jamb_reg_no:
1789            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1790            if res:
1791                return '',"jamb_reg_no exists"
1792        matric_no = mapping.get('matric_no',None)
1793        if matric_no:
1794            res = self.students_catalog(matric_no = matric_no)
1795            if res:
1796                return '',"matric_no exists"
1797        sid = self.waeup_tool.generateStudentId('?')
1798        students_folder.invokeFactory('Student', sid)
1799        student_obj = getattr(students_folder,sid)
1800        f2t = self.field2types_student
1801        d = {}
1802        transition = mapping.get('reg_transition','admit')
1803        if transition not in ('admit','return'):
1804            return '',"no valid transition provided"
1805        for pt in f2t.keys():
1806            student_obj.invokeFactory(pt,f2t[pt]['id'])
1807            sub_obj = getattr(student_obj,f2t[pt]['id'])
1808            sub_doc = sub_obj.getContent()
1809            d['Title'] = f2t[pt]['title']
1810            for field in f2t[pt]['fields']:
1811                d[field] = mapping.get(field,'')
1812
1813            if pt == "StudentApplication":
1814                #d['jamb_sex']  = 'M'
1815                #if mapping.get('sex'):
1816                #    d['jamb_sex']  = 'F'
1817                d['jamb_firstname'] = mapping.get('firstname',None)
1818                d['jamb_middlename'] = mapping.get('middlename',None)
1819                d['jamb_lastname'] = mapping.get('lastname',None)
1820
1821            # if pt == "StudyCourse":
1822            #     for von,zu in (('entry_mode','current_mode'),
1823            #                    ('entry_session','current_session')):
1824            #         if mapping.get(zu,None) is None and mapping.get(von,None) is not None:
1825            #             d[zu] = mapping[von]
1826            sub_doc.edit(mapping = d)
1827
1828            #import pdb;pdb.set_trace()
1829            new_state = f2t[pt]['wf_transition_%(transition)s' % vars()]
1830            if new_state != "remain":
1831                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1832        self.portal_workflow.doActionFor(student_obj,transition)
1833        student_obj.manage_setLocalRoles(sid, ['Owner',])
1834        return sid,''
1835    ###)
1836
1837    security.declareProtected(ModifyPortalContent,'mass_edit_student') ###(
1838    def mass_edit_student(self,mapping):
1839        wftool = self.portal_workflow
1840        "edit student records due import"
1841        logger = logging.getLogger('WAeUPTool.mass_edit_student')
1842        students_folder = self.portal_url.getPortalObject().campus.students
1843        sid = mapping.get('id',None)
1844        jamb_reg_no = mapping.get('jamb_reg_no',None)
1845        matric_no = mapping.get('matric_no',None)
1846        editable_keys = mapping.keys()
1847        if sid:
1848            res = self.students_catalog(id = sid)
1849            if not res:
1850                return '',"no student with id %s" % sid
1851            if matric_no and res[0].matric_no and\
1852              matric_no != res[0].matric_no:
1853                logger.info("%s, old matric_no %s overwritten with %s" % (res[0].id,res[0].matric_no,matric_no))
1854            if jamb_reg_no and res[0].jamb_reg_no and\
1855              jamb_reg_no != res[0].jamb_reg_no:
1856                logger.info("%s, old reg_no %s overwritten with %s" % (res[0].id,res[0].jamb_reg_no,jamb_reg_no))
1857        elif jamb_reg_no:
1858            res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1859            if not res:
1860                return '',"no student with jamb_reg_no %s" % jamb_reg_no
1861            editable_keys.remove('jamb_reg_no')
1862        elif matric_no:
1863            res = self.students_catalog(matric_no = matric_no)
1864            if not res:
1865                return '',"no student with matric_no %s" % matric_no
1866            editable_keys.remove('matric_no')
1867
1868        ## included only to change wf state from admitted to returning
1869        #if res[0].review_state not in ('admitted','objection_raised'):
1870        #    return '%s' % res[0].id ,"student is not in state admitted or objection_raised"
1871        ## end inclusion
1872
1873        sid = res[0].id
1874        student_obj = getattr(students_folder,sid)
1875        f2t = self.field2types_student
1876        d = {}
1877        #import pdb;pdb.set_trace()
1878        any_change = False
1879        #special treatment for StudentStudyLevel
1880        d['verdict']  = mapping.get('current_verdict','')
1881        d['session']  = mapping.get('current_session','')
1882        current_level = mapping.get('current_level','')
1883        while d['session'] and d['verdict'] and current_level:
1884            sub_obj = getattr(student_obj,'study_course',None)
1885            if sub_obj is None:
1886                break
1887            level_obj = getattr(sub_obj,current_level,None)
1888            if  level_obj is None:
1889                break
1890            any_change = True
1891            level_obj.getContent().edit(mapping = d)
1892            try:
1893                wftool.doActionFor(level_obj,'close')
1894            except:
1895                pass
1896            break
1897        for pt in f2t.keys():
1898            #if pt == "StudentApplication":
1899            #    d['jamb_sex']  = 'M'
1900            #    if mapping.get('sex'):
1901            #        d['jamb_sex']  = 'F'
1902            intersect = set(f2t[pt]['fields']).intersection(set(editable_keys))
1903            if intersect and pt not in ('StudentStudyLevel',):
1904                object_id = f2t[pt]['id']
1905                sub_obj = getattr(student_obj,object_id,None)
1906                if sub_obj is None:
1907                    try:
1908                        student_obj.invokeFactory(pt,object_id)
1909                    except:
1910                        continue
1911                    sub_obj = getattr(student_obj,object_id)
1912                    if f2t[pt]['title'] != '':
1913                        d['Title'] = f2t[pt]['title']
1914                sub_doc = sub_obj.getContent()
1915                for field in intersect:
1916                    changed = False
1917                    if getattr(sub_doc,field,None) != mapping.get(field,''):
1918                        any_change = True
1919                        changed = True
1920                        d[field] = mapping.get(field,'')
1921                    if changed:
1922                        sub_doc.edit(mapping = d)
1923
1924
1925        ## included only to change wf state from admitted to returning
1926        #    if res[0].review_state in ('admitted','objection_raised'):
1927        #        new_state = f2t[pt]['wf_transition_return']
1928        #        sub_obj = getattr(student_obj,f2t[pt]['id'],None)
1929        #        if sub_obj and new_state != "remain":
1930        #            try:
1931        #                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1932        #            except:
1933        #                #logger.info('%s, wf transition %s of %s failed' % (sid,new_state,sub_obj.id))
1934        #                pass
1935        #if res[0].review_state in ('admitted','objection_raised'):
1936        #    wfaction = 'return'
1937        #    try:
1938        #        self.portal_workflow.doActionFor(student_obj,wfaction)
1939        #        logger.info('%s, wf state changed' % sid)
1940        #        any_change = True
1941        #    except:
1942        #        logger.info('%s, wf transition failed, old state = %s' % (sid,res[0].review_state))
1943        #        pass
1944        ## end inclusion
1945
1946
1947        if any_change:
1948            return sid,''
1949        else:
1950            return sid,'not modified'
1951    ###)
1952
1953    security.declareProtected(ModifyPortalContent,'mass_edit_verdict') ###(
1954    def mass_edit_verdict(self,mapping):
1955        wftool = self.portal_workflow
1956        "edit student verdicts"
1957        logger = logging.getLogger('WAeUPTool.mass_edit_verdict')
1958        students_folder = self.portal_url.getPortalObject().campus.students
1959        student_id = mapping.get('id',None)
1960        matric_no = mapping.get('matric_no',None)
1961        editable_keys = mapping.keys()
1962        if student_id:
1963            student_record = self.students_catalog.getRecordByKey(student_id)
1964            if student_record is None:
1965                return '',"no student with id %s" % student_id
1966            if matric_no and student_record.matric_no and\
1967              matric_no != student_record.matric_no:
1968                return '', 'student %s: matric_no %s does not match %s' % (student_record.id,
1969                                                                          student_record.matric_no,
1970                                                                          matric_no)
1971            mapping['matric_no'] = student_record.matric_no
1972        elif matric_no:
1973            res = self.students_catalog(matric_no = matric_no)
1974            if not res:
1975                return '',"no student with matric_no %s" % matric_no
1976            student_record = res[0]
1977            editable_keys.remove('matric_no')
1978        else:
1979            return '',"no id or matric_no specified"
1980        student_id = student_record.id
1981        d = {}
1982        #import pdb;pdb.set_trace()
1983        any_change = False
1984        #special treatment for StudentStudyLevel
1985        current_session = d['session'] = mapping.get('current_session','')
1986        if current_session and student_record.session != current_session:
1987            msg = 'student %s: imported session %s does not match current_session %s' % (student_id,
1988                                                                                        current_session,
1989                                                                                        student_record.session)
1990            return student_id,msg,mapping
1991        current_level = mapping.get('current_level','')
1992        if not current_level.isdigit():
1993            return '','student %s: imported level is empty' % (student_id,)
1994        if current_level and student_record.level != current_level:
1995            msg = 'student %s: imported level %s does not match current_level %s' % (student_id,
1996                                                                                    current_level,
1997                                                                                    student_record.level)
1998            return student_id,msg,mapping
1999        student_review_state =  student_record.review_state
2000        if student_review_state == 'deactivated':
2001            return '',"student %s in review_state %s" % (student_id, student_review_state)
2002        if student_review_state not in ('courses_validated','returning'):
2003            msg = "student %s in wrong review_state %s" % (student_id, student_review_state)
2004            return student_id,msg,mapping
2005        student_obj = getattr(students_folder,student_id)
2006        f2t = self.field2types_student
2007        study_course_obj = getattr(student_obj,'study_course',None)
2008        if study_course_obj is None:
2009            return '','student %s: no study_course object' % student_id
2010        level_obj = getattr(study_course_obj,current_level,None)
2011        if  level_obj is None:
2012            return '','student %s: no study_level object for level %s' % (student_id,
2013                                                                             current_level)
2014        verdict = d['verdict'] = d['current_verdict']  = mapping.get('current_verdict','')
2015
2016        #if verdict == student_record.verdict:
2017        #    return '','student %s: verdict already set to %s' % (student_id,
2018        #                                                            verdict)
2019
2020        level_review_state = wftool.getInfoFor(level_obj,'review_state',None)
2021        if level_review_state != "closed":
2022            wftool.doActionFor(level_obj,'close')
2023            # return '','student %s: level %s is not closed' % (student_id,
2024            #                                                      current_level)
2025
2026        study_course_obj.getContent().edit(mapping = d)
2027        level_obj.getContent().edit(mapping = d)
2028        if student_review_state != "returning":
2029            wftool.doActionFor(student_obj,'return')
2030        # try:
2031        #     wftool.doActionFor(level_obj,'close')
2032        # except:
2033        #     pass
2034        return student_id,''
2035    ###)
2036
2037    security.declareProtected(ModifyPortalContent,"importData")###(
2038    def importData(self,filename,name,edit=False,bypass_queue_catalog=False):
2039        """load data from CSV values"""
2040        import transaction
2041        import random
2042        member = self.portal_membership.getAuthenticatedMember()
2043        logger = logging.getLogger('WAeUPTool.importData')
2044        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
2045        import_date = DateTime.DateTime().strftime("%d/%m/%y %H:%M:%S")
2046        students_folder = self.portal_url.getPortalObject().campus.students
2047        start = True
2048        tr_count = 0
2049        total_imported = 0
2050        total_not_imported = 0
2051        total = 0
2052        pending_only = False
2053        pend_str = '_pending'
2054        if name.endswith(pend_str):
2055            pending_only = True
2056            name = name[:-len(pend_str)]
2057        iname = "import_%s" % name
2058        if name in ('application','course_result',):
2059            commit_after = 2000
2060        else:
2061            commit_after = 100
2062        stool = getToolByName(self, 'portal_schemas')
2063        ltool = getToolByName(self, 'portal_layouts')
2064        schema = stool._getOb(iname)
2065        if schema is None:
2066            em = 'No such schema %s' % iname
2067            logger.error('No such schema %s' % iname)
2068            return em
2069        layout = ltool._getOb(iname)
2070        if layout is None:
2071            em = 'No such layout %s' % iname
2072            logger.error(em)
2073            return em
2074        validators = {}
2075        for widget in layout.keys():
2076            validators[widget] = layout[widget].validate
2077        mode = "create"
2078        if edit:
2079            if filename.endswith('_toDelete'):
2080                mode = "delete"
2081            else:
2082                mode = "edit"
2083        importer_name = "mass_%(mode)s_%(name)s" % vars()
2084        importer = getattr(self, '%s' % importer_name,None)
2085        if importer is None:
2086            em = 'No importer function %s' % importer_name
2087            logger.error(em)
2088            return em
2089        pending_fn = "%s/import/%ss_pending.csv" % (i_home,name)
2090        pending_imported_fn = "%s/import/%ss_pending_imported%s.csv" % (i_home,name,current)
2091        if pending_only:
2092            import_source_fn = pending_fn
2093            imported_fn = "%s/import/%ss_pending_imported%s.csv" % (i_home,name,current)
2094            not_imported_fn = "%s/import/%ss_pending_not_imported%s.csv" % (i_home,name,current)
2095            if not os.path.exists(pending_fn):
2096                em = 'No  %s' % os.path.split(pending_fn)
2097                return em
2098        else:
2099            import_source_fn = "%s/import/%s.csv" % (i_home,filename)
2100            imported_fn = "%s/import/%s_imported%s.csv" % (i_home,filename,current)
2101            not_imported_fn = "%s/import/%s_not_imported%s.csv" % (i_home,filename,current)
2102        if not os.path.exists(import_source_fn):
2103            em = 'No  %s' % os.path.split(import_soure_fn)
2104            return em
2105        attrs = csv.reader(open(import_source_fn,"rb")).next()
2106        import_keys = [k.strip() for k in attrs if not (k.strip().startswith('ignore')
2107                                                        or k.strip() == 'Error')]
2108        diff2schema = set(import_keys).difference(set(schema.keys()))
2109        diff2layout = set(import_keys).difference(set(layout.keys()))
2110        if diff2schema and diff2schema != set(['id',]):
2111            msg = 'not ignorable key(s): "%s" found in heading' % ", ".join(diff2schema)
2112            return msg
2113        if mode in ("create","edit"):
2114            required_keys = [layout.getIdUnprefixed(id)
2115                                for id,widget in layout.objectItems()
2116                                if widget.is_required]
2117            if not set(required_keys).issubset(set(import_keys)):
2118                diff2import = set(required_keys).difference(set(import_keys))
2119                msg = 'required key(s): "%s" not found in heading' % ", ".join(diff2import)
2120                return msg
2121        #
2122        # not_imported
2123        #
2124        not_imported_keys = import_keys + ["Error",]
2125        not_imported_file = open(not_imported_fn,"w")
2126        not_imported_csv_writer = csv.DictWriter(not_imported_file,
2127                                                    not_imported_keys,
2128                                                    extrasaction='ignore')
2129        mapping = dict((k,k) for k in not_imported_keys)
2130        not_imported_csv_writer.writerow(mapping)
2131        not_imported = []
2132        #
2133        # imported
2134        #
2135        imported_keys = import_keys[:]
2136        if 'id' not in imported_keys:
2137            imported_keys.insert(0,"id")
2138        imported_file = open(imported_fn,"w")
2139        imported_csv_writer = csv.DictWriter(imported_file,
2140                                             imported_keys,
2141                                             extrasaction='ignore')
2142        mapping = dict((k,k) for k in imported_keys)
2143        imported_csv_writer.writerow(mapping)
2144        imported = []
2145        #
2146        # pending
2147        #
2148        pending_records = {}
2149        imports_pending = 0
2150        total_pending_imported = 0
2151        total_pending = 0
2152        format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
2153        format_error = format + ',"%(Error)s"'
2154        #format = '"%(id)s",'+ format
2155        imported = []
2156        if name in ('verdict','course_result',):
2157            #pending_keys = imported_keys[:]
2158            sname = "%s_pending" % iname
2159            pending_schema = stool._getOb(sname)
2160            if schema is None:
2161                em = 'No such pending_schema %s' % sname
2162                logger.error('No such schema %s' % sname)
2163                return em
2164            pending_keys = pending_schema.keys()
2165            pending_keys += "Error",
2166            if 'id' not in pending_keys:
2167                pending_keys.insert(0,'id')
2168            pending_records = {}
2169            if os.path.exists(pending_fn):
2170                pending_imports_file = open(pending_fn)
2171                pending_imports = csv.DictReader(pending_imports_file,
2172                                                 fieldnames=pending_keys)
2173                if pending_imports:
2174                    pending_records = dict((row['id'],row) for row in pending_imports
2175                                          if row['id'] != 'id')
2176                pending_imports_file.close()
2177            new_imports_pending = 0
2178            pending_imported = []
2179            if pending_only:
2180                pending_imported_ids = []
2181                pending_imported = []
2182                for record in pending_records.values():
2183                    item = {}
2184                    for k,v in record.items():
2185                        if v:
2186                            item[k] = v
2187                    results = importer(item)
2188                    id = results[0]
2189                    error = results[1]
2190                    is_pending = len(results) == 3
2191                    if is_pending:
2192                        continue
2193                    del item['Error']
2194                    msg = ";".join(["%s : %s" % (k,v) for k,v in item.items()])
2195                    logger.info("imported from %(pending_fn)s %(msg)s" % vars())
2196                    pending_imported.append(item)
2197                    pending_imported_ids += id,
2198                    total_pending_imported = len(pending_imported_ids)
2199                    logger.info("imported %d pending imports" % len(pending_imported_ids))
2200                for id in pending_imported_ids:
2201                    if id:
2202                        del pending_records[id]
2203                    else:
2204                        logger.info("tried to delete record with empty id")
2205            pending_imports_file = open(pending_fn,'w')
2206            pending_csv_writer = csv.DictWriter(pending_imports_file,
2207                                                pending_keys,
2208                                                extrasaction='ignore')
2209            mapping = dict((k,k) for k in pending_keys)
2210            pending_csv_writer.writerow(mapping)
2211            if len(pending_imported) > 0:
2212                pending_imported_file = open(pending_imported_fn,'w')
2213                pending_imported_csv_writer = csv.DictWriter(pending_imported_file,
2214                                                             pending_keys,
2215                                                             extrasaction='ignore')
2216                pending_imported_csv_writer.writerow(dict((k,k) for k in imported_keys))
2217                pending_imported_csv_writer.writerows(pending_imported)
2218        #
2219        if pending_only:
2220            items = []
2221        else:
2222            try:
2223                items = csv.DictReader(open(import_source_fn,"rb"))
2224            except:
2225                msg = 'Error reading %s.csv' % filename
2226                logger.error(msg)
2227                return msg
2228            not_imported = []
2229        pending_keys = pending_records.keys()[:]
2230        for item in items:
2231            item = dict((k.strip(),l.strip()) for (k,l) in item.items())
2232            if start:
2233                start = False
2234                adapters = [MappingStorageAdapter(schema, item)]
2235                logger.info('%s starts import from %s.csv in %s mode with schema and layout %s' % (member,filename,mode,iname))
2236            dm = DataModel(item, adapters,context=self)
2237            ds = DataStructure(data=item,datamodel=dm)
2238            error_string = ""
2239            total += 1
2240            error_count = 0
2241            for k in import_keys:
2242                if not validators[k](ds,mode=mode):
2243                    if error_count:
2244                        error_string += ' ++ '
2245                    error_string += "%s: %s" % (k,self.translation_service(ds.getError(k),
2246                                                                           ds.getErrorMapping(k)))
2247                    error_count += 1
2248            if error_string:
2249                item['Error'] = error_string
2250                not_imported.append(item)
2251                total_not_imported += 1
2252                continue
2253            temp_item = item.copy()
2254            temp_item.update(dm)
2255            #id,error = importer(temp_item)
2256            results = importer(temp_item)
2257            id = results[0]
2258            error = results[1]
2259            is_pending = len(results) == 3
2260            if is_pending:
2261                temp_item = results[2]
2262                temp_item['Error'] = error
2263                msg = format_error % temp_item
2264                #if id not in pending_records.keys():
2265                if id not in pending_keys:
2266                    temp_item['id'] = id
2267                    pending_records[id] = temp_item
2268                    logger.info("%(id)s added to pending %(msg)s" % vars())
2269                    pending_keys += id,
2270                    new_imports_pending += 1
2271                else:
2272                    logger.info("%(id)s already in pending %(msg)s" % vars())
2273                continue
2274            elif error:
2275                item['Error'] = error
2276                not_imported.append(item)
2277                total_not_imported += 1
2278                continue
2279            item = temp_item
2280            item['id'] = id
2281            imported.append(item)
2282            tr_count += 1
2283            total_imported += 1
2284            msg = format % item
2285            logger.info("%(total_imported)d of %(total)d imported in %(mode)s mode, %(msg)s" % vars())
2286            if total and not total % commit_after:
2287                transaction.commit()
2288                if len(imported) > 0:
2289                    imported_csv_writer.writerows(imported)
2290                    imported = []
2291                if len(not_imported) > 0:
2292                    not_imported_csv_writer.writerows(not_imported)
2293                    not_imported = []
2294                if len(pending_records) > 0:
2295                    pending_csv_writer.writerows(pending_records.values())
2296                    total_pending += len(pending_records)
2297                    pending_records = {}
2298                msg = '%d transactions committed\n' % (tr_count)
2299                regs = []
2300                logger.info(msg)
2301                tr_count = 0
2302        if len(imported) > 0:
2303            imported_csv_writer.writerows(imported)
2304        if len(not_imported) > 0:
2305            not_imported_csv_writer.writerows(not_imported)
2306        if len(pending_records) > 0:
2307            pending_csv_writer.writerows(pending_records.values())
2308            total_pending += len(pending_records)
2309        import_source_fn = os.path.split(import_source_fn)[1]
2310        pending_fn = os.path.split(pending_fn)[1]
2311        msg = "Finished importing in %(mode)s mode from %(import_source_fn)s: " % vars()
2312        msg += "%(total_imported)d imported, %(total_not_imported)d not imported, " % vars()
2313        if total_pending:
2314            if pending_only:
2315                msg += "%(new_imports_pending)d pending added, %(total_pending_imported)d pending imported " % vars()
2316            else:
2317                msg += "%(new_imports_pending)d pending added " % vars()
2318            msg += "(of total %(total)d), " % vars()
2319            msg += "%(total_pending)d total pending in %(pending_fn)s " % vars()
2320        logger.info(msg)
2321        return msg
2322    ###)
2323
2324    def old_importData(self,filename,name,edit=False,bypass_queue_catalog=False):###(
2325        """load data from CSV values"""
2326        import transaction
2327        import random
2328
2329        pm = self.portal_membership
2330        member = pm.getAuthenticatedMember()
2331
2332        logger = logging.getLogger('WAeUPTool.importData')
2333        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
2334        students_folder = self.portal_url.getPortalObject().campus.students
2335        start = True
2336        tr_count = 0
2337        total_imported = 0
2338        total_not_imported = 0
2339        total = 0
2340        iname = "import_%s" % name
2341        if iname in ('import_application','import_course_result',):
2342            commit_after = 2000
2343        else:
2344            commit_after = 100
2345        stool = getToolByName(self, 'portal_schemas')
2346        ltool = getToolByName(self, 'portal_layouts')
2347        schema = stool._getOb(iname)
2348        if schema is None:
2349            em = 'No such schema %s' % iname
2350            logger.error('No such schema %s' % iname)
2351            return em
2352        layout = ltool._getOb(iname)
2353        if layout is None:
2354            em = 'No such layout %s' % iname
2355            logger.error(em)
2356            return em
2357        validators = {}
2358        for widget in layout.keys():
2359            validators[widget] = layout[widget].validate
2360        mode = "create"
2361        if edit:
2362            if filename.endswith('_toDelete'):
2363                mode = "delete"
2364            else:
2365                mode = "edit"
2366        importer_name = "mass_%(mode)s_%(name)s" % vars()
2367        importer = getattr(self, '%s' % importer_name,None)
2368        if importer is None:
2369            em = 'No importer function %s' % importer_name
2370            logger.error(em)
2371            return em
2372        not_imported = []
2373        imported = []
2374        try:
2375            items = csv.DictReader(open("%s/import/%s.csv" % (i_home,filename),"rb"))
2376        except:
2377            em = 'Error reading %s.csv' % filename
2378            logger.error(em)
2379            return em
2380        for item in items:
2381            #import pdb;pdb.set_trace()
2382            item = dict((k.strip(),l.strip()) for (k,l) in item.items())
2383            if start:
2384                start = False
2385                adapters = [MappingStorageAdapter(schema, item)]
2386                logger.info('%s starts import from %s.csv in %s mode with schema and layout %s' % (member,filename,mode,iname))
2387                attrs = csv.reader(open("%s/import/%s.csv" % (i_home,filename),"rb")).next()
2388                import_keys = [k.strip() for k in attrs if not k.strip().startswith('ignore')]
2389                diff2schema = set(import_keys).difference(set(schema.keys()))
2390                diff2layout = set(import_keys).difference(set(layout.keys()))
2391                if diff2schema:
2392                    em = 'not ignorable key(s): "%s" found in heading' % ", ".join(diff2schema)
2393                    return em
2394                if mode == "create":
2395                    required_keys = [layout.getIdUnprefixed(id)
2396                                     for id,widget in layout.objectItems()
2397                                     if widget.is_required]
2398                    if not set(required_keys).issubset(set(import_keys)):
2399                        diff2import = set(required_keys).difference(set(import_keys))
2400                        em = 'required key(s): "%s" not found in heading' % ", ".join(diff2import)
2401                        return em
2402                s = ','.join(['"%s"' % fn for fn in import_keys])
2403                open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(s + ',"Error"'+ '\n')
2404                s = '"id",' + s
2405                open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(s + '\n')
2406                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
2407                format_error = format + ',"%(Error)s"'
2408                format = '"%(id)s",'+ format
2409
2410            dm = DataModel(item, adapters,context=self)
2411            ds = DataStructure(data=item,datamodel=dm)
2412            error_string = ""
2413            total += 1
2414            error_count = 0
2415            for k in import_keys:
2416                if not validators[k](ds,mode=mode):
2417                    if error_count:
2418                        error_string += ' ++ '
2419                    error_string += "%s: %s" % (k,
2420                                                  self.translation_service(ds.getError(k),
2421                                                                           ds.getErrorMapping(k)))
2422                    error_count += 1
2423            if not error_string:
2424                temp_item = item.copy()
2425                temp_item.update(dm)
2426                temp_item['id'],error = importer(temp_item)
2427                if error:
2428                    error_string += error
2429                else:
2430                    item = temp_item
2431            if error_string:
2432                item['Error'] = error_string
2433                not_imported.append(format_error % item)
2434                total_not_imported += 1
2435            else:
2436                em = format % item
2437                imported.append(em)
2438                tr_count += 1
2439                total_imported += 1
2440                logger.info("%(total_imported)d of %(total)d imported in %(mode)s mode, %(em)s" % vars())
2441
2442            if total and not total % commit_after:
2443                transaction.commit()
2444                if len(not_imported) > 0:
2445                    open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
2446                             '\n'.join(not_imported) + '\n')
2447                    not_imported = []
2448                if len(imported) > 0:
2449                    open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
2450                             '\n'.join(imported) + '\n')
2451                    imported = []
2452                em = '%d transactions committed\n' % (tr_count)
2453                regs = []
2454                logger.info(em)
2455                tr_count = 0
2456                #if total > 100:
2457                #    return
2458        if len(imported) > 0:
2459            open("%s/import/%s_imported%s.csv" % (i_home,filename,current),"a").write(
2460                                                '\n'.join(imported))
2461        if len(not_imported) > 0:
2462            open("%s/import/%s_not_imported%s.csv" % (i_home,filename,current),"a").write(
2463                                                '\n'.join(not_imported))
2464        #if mode.endswith('e'):
2465        #    mode = mode[:-1]
2466        em = "Finished importing in %(mode)s mode from %(filename)s.csv: %(total_imported)d imported, %(total_not_imported)d not imported (of total %(total)d)" % vars()
2467        logger.info(em)
2468        return em
2469    ###)
2470
2471    security.declareProtected(ModifyPortalContent,"moveImagesToFS")###(
2472    def moveImagesToFS(self,student_id="O738726"):
2473        "move the images to the filesystem"
2474        images_dir = getImagesDir(student_id)
2475        #images_dir = os.path.join("%s" % images_base,student_id)
2476        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
2477        stool = getToolByName(self, 'portal_schemas')
2478        schemas = ['student_application',
2479                   'student_clearance',
2480                   ]
2481        created = False
2482        for schema_id in schemas:
2483            schema = stool._getOb(schema_id)
2484            object = getattr(student_folder,schema_id[len('student_'):],None)
2485            if object is None:
2486                continue
2487            doc = object.getContent()
2488            for key in schema.keys():
2489                if schema[key].meta_type != "CPS Image Field":
2490                    continue
2491                #import pdb;pdb.set_trace()
2492                image = getattr(doc,key,None)
2493                if not image or not hasattr(image,"data"):
2494                    continue
2495                if not created:
2496                    if not os.path.exists(images_dir):
2497                        os.mkdir(images_dir)
2498                    created = True
2499                filename = os.path.join(images_dir,"%(key)s_%(student_id)s.jpg" % vars())
2500                open(filename,"wb").write(str(image.data))
2501    ###)
2502
2503    security.declareProtected(ModifyPortalContent,"movePassportToFS")###(
2504    def movePassportToFS(self,student_id="O738726"):
2505        "move the passports to the filesystem"
2506        images_dir = os.path.join("%s" % i_home,'passports')
2507        student_folder = getattr(self.portal_url.getPortalObject().campus.students,student_id)
2508        stool = getToolByName(self, 'portal_schemas')
2509        schemas = ['student_application',
2510                   #'student_clearance',
2511                   ]
2512        created = False
2513        for schema_id in schemas:
2514            schema = stool._getOb(schema_id)
2515            object = getattr(student_folder,schema_id[len('student_'):],None)
2516            if object is None:
2517                continue
2518            doc = object.getContent()
2519            for key in schema.keys():
2520                if schema[key].meta_type != "CPS Image Field":
2521                    continue
2522                #import pdb;pdb.set_trace()
2523                image = getattr(doc,key)
2524                if not hasattr(image,"data"):
2525                    continue
2526                if not created:
2527                    if not os.path.exists(images_dir):
2528                        os.mkdir(images_dir)
2529                    created = True
2530                filename = os.path.join(images_dir,"%(student_id)s.jpg" % vars())
2531                open(filename,"wb").write(str(image.data))
2532    ###)
2533
2534InitializeClass(WAeUPTool)
Note: See TracBrowser for help on using the repository browser.