source: WAeUP_SRP/trunk/WAeUPImport.py @ 3982

Last change on this file since 3982 was 3977, checked in by Henrik Bettermann, 16 years ago

increase commit_after of verdict import

  • Property svn:keywords set to Id
File size: 63.3 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: WAeUPImport.py 3977 2009-02-23 23:21:02Z henrik $
20"""The WAeUP Tool Box.
21"""
22
23#from AccessControl import ClassSecurityInfo
24#from Acquisition import aq_inner
25#from Acquisition import aq_parent
26#from Globals import DTMLFile
27#from Globals import InitializeClass
28from OFS.SimpleItem import SimpleItem
29from zExceptions import BadRequest
30
31#from Products.CMFCore.utils import getToolByName
32#from Products.CPSSchemas.DataStructure import DataStructure
33#from Products.CPSSchemas.DataModel import DataModel
34#from Products.CPSSchemas.StorageAdapter import MappingStorageAdapter
35from Products.CMFCore.ActionProviderBase import ActionProviderBase
36#from Products.CMFCore.permissions import View
37#from Products.ZCatalog.ZCatalog import ZCatalog
38#from Products.CMFCore.permissions import ModifyPortalContent
39#from Products.CMFCore.permissions import ManagePortal
40from Products.CMFCore.utils import UniqueObject
41#from Products.CMFCore.URLTool import URLTool
42from Products.CMFCore.utils import getToolByName
43from Globals import package_home,INSTANCE_HOME
44from Products.AdvancedQuery import Eq, Between, Le,In
45import csv,re,os,sys
46from shutil import copy2
47import DateTime,time
48import logging
49p_home = package_home(globals())
50i_home = INSTANCE_HOME
51from utils import makeDigest
52
53NO_KEY = '----'
54IGNORE = 'ignore'
55class WAeUPImport(UniqueObject, SimpleItem, ActionProviderBase): ###(
56    """ WAeUPImport """
57    required_modes = ('create',)
58
59    def __init__(self,waeup_tool): ###(
60        self.students_folder = waeup_tool.portal_url.getPortalObject().campus.students
61        self.member = member = waeup_tool.portal_membership.getAuthenticatedMember()
62        self.import_date = DateTime.DateTime()
63        self.imported_by = str(member)
64        #self.current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
65        self.waeup_tool = waeup_tool
66        self.academics_folder = waeup_tool.portal_url.getPortalObject().campus.academics
67        self.schema_tool = getToolByName(waeup_tool, 'portal_schemas')
68        self.layout_tool = getToolByName(waeup_tool, 'portal_layouts')
69        self.types_tool = getToolByName(waeup_tool, 'portal_types')
70        self.portal_workflow = getToolByName(waeup_tool, 'portal_workflow')
71        self.portal_url = getToolByName(waeup_tool, 'portal_url')
72        self.portal_catalog = waeup_tool.portal_catalog
73        self.portal_directories = waeup_tool.portal_directories
74        self.students_catalog = waeup_tool.students_catalog
75        self.courses_catalog = waeup_tool.courses_catalog
76        self.course_results = waeup_tool.course_results
77        self.applicants_catalog = waeup_tool.applicants_catalog
78        #self.mode = mode
79        # self.import_method = getattr(self, '%s' % mode,None)
80        errors = []
81        # if self.import_method is None:
82        #     errors.append('No importer method %s' % mode)
83        self.pending_path = "%s/import/%s.pending" % (i_home,self.plural_name)
84        self.pending_tmp = "%s/import/%s.pending.tmp" % (i_home,self.plural_name)
85        self.pending_backup = "%s/import/%s.pending.old" % (i_home,self.plural_name)
86        self.pending_fn = os.path.split(self.pending_path)[1]
87        self.imported_path = "%s/import/%s.imported" % (i_home,self.plural_name)
88        self.imported_fn = os.path.split(self.imported_path)[1]
89        iname = "import_%s" % self.name
90        self.logger = logging.getLogger('WAeUPImport.%sImport' % self.plural_name.capitalize())
91        self.schema = self.schema_tool._getOb(iname,None)
92        #self.pending_schema = self.schema_tool._getOb("%s_pending" % iname,None)
93        self.layout = self.layout_tool._getOb(iname,None)
94        while True:
95            if self.schema is None:
96                errors.append('no schema %s' % iname)
97            # if self.pending_schema is None:
98            #     self.pending_schema = self.schema
99            if self.layout is None:
100                errors.append('no such layout %s' % iname)
101            if errors:
102                break
103            self.data_keys = self.schema.keys()
104            self.csv_keys = self.schema.keys()
105            info = {}
106            info['imported_from'] = ''
107            info['import_record_no'] = 0
108            info['imported_by'] = self.imported_by
109            info['import_date'] = self.import_date.strftime("%d/%m/%y %H:%M:%S")
110            info['error'] = ''
111            self.info = info
112            self.csv_keys.extend(self.info)
113            self.validators = {}
114            for widget in self.layout.keys():
115                self.validators[widget] = self.layout[widget].validate
116            self.required_keys = {}
117            for mode in self.required_modes:
118                self.required_keys[mode] = [self.layout.getIdUnprefixed(id)
119                                    for id,widget in self.layout.objectItems()
120                                    if widget.is_required]
121            break
122        self.init_errors = ','.join(errors)
123    ###)
124
125    def findStudent(self,mode,student_id=None, matric_no=None, jamb_reg_no=None): ###(
126        student_record = None
127        msg = ''
128        key_used = ''
129        while True:
130            if student_id:
131                key_used = 'student_id'
132                res = self.students_catalog(id = student_id)
133                if not res:
134                    msg = "no student with id %s" % student_id
135                    break
136                student_record = res[0]
137                if matric_no and student_record.matric_no:
138                    if  matric_no != student_record.matric_no:
139                        msg = "old matric_no %s overwritten with %s" % (student_record.matric_no,matric_no)
140                        #logger.info("%s, old matric_no %s overwritten with %s" % (student_record.id,student_record.matric_no,matric_no))
141                if jamb_reg_no and student_record.jamb_reg_no:
142                    if jamb_reg_no != student_record.jamb_reg_no:
143                        msg = "old reg_no %s overwritten with %s" % (student_record.jamb_reg_no,jamb_reg_no)
144                        #logger.info("%s, old reg_no %s overwritten with %s" % (student_record.id,student_record.jamb_reg_no,jamb_reg_no))
145            elif jamb_reg_no:
146                key_used = 'jamb_reg_no'
147                res = self.students_catalog(jamb_reg_no = jamb_reg_no)
148                if res:
149                    if mode == 'create':
150                        msg = "jamb_reg_no exists"
151                        break
152                else:
153                    if mode == 'edit':
154                        msg = "no student with jamb_reg_no %s" % jamb_reg_no
155                        break
156                student_record = res[0]
157            elif matric_no:
158                key_used = 'matric_no'
159                res = self.students_catalog(matric_no = matric_no)
160                if not res:
161                    msg = "no student with matric_no %s" % matric_no
162                    break
163                student_record = res[0]
164            else:
165                msg = "neither id, matric_no nor reg_no specified"
166            break
167        d = {}
168        d['student_record'] = student_record
169        d['key_used'] = key_used
170        d['msg'] = msg
171        return d
172    ###)
173
174    def makeIdLists(self): ###(
175        pending_digests = []
176        pending = []
177        # pending_student_ids = []
178        # pending_matric_nos = []
179        # pending_reg_ns = []
180        if os.path.exists(self.pending_path):
181            datafile = open(self.pending_path,"r")
182            reader = csv.reader(datafile)
183            old_headline = reader.next()
184            #datafile.seek(0)
185            pending_csv_reader = csv.DictReader(datafile,old_headline,)
186            #pending_csv_reader.next() # skip headline
187            for item in pending_csv_reader:
188                digest = makeDigest(item,self.data_keys)
189                if digest not in pending_digests:
190                    pending_digests += digest,
191                    pending += item,
192            datafile.close()
193            #copy2(self.pending_path,self.pending_backup)
194        return pending, pending_digests
195    ###)
196
197    def checkHeadline(self,headline): ###(
198        """ check the headline of a csv file """
199        import_keys = [k.strip() for k in headline if not (k.strip().startswith('ignore')
200                                                        or k.strip() in self.info.keys())]
201        # import_keys = [k.strip() for k in headline if not (k.strip() in self.info.keys())]
202        diff2schema = set(import_keys).difference(set(self.schema.keys()))
203        diff2layout = set(import_keys).difference(set(self.layout.keys()))
204        #if diff2schema and diff2schema != set(['id',]):
205        if diff2schema:
206            return list(diff2schema)
207        return []
208    ###)
209
210    def getHeadlineFields(self,headline,values): ###(
211        """ check the headline of a csv file """
212        # import_keys = [k.strip() for k in headline if not (k.strip().startswith('ignore')
213        #                                                 or k.strip() in self.info.keys())]
214        import_keys = [k.strip() for k in headline if not (k.strip() in self.info.keys())]
215        info_keys = [k.strip() for k in headline if k.strip() in self.info.keys()]
216        si = set(import_keys)
217        ss = set(self.schema.keys())
218
219        invalid_keys = si - ss
220        keys = []
221        i = 0
222        duplicates = False
223        singels = []
224        msg = ''
225        while True:
226            if len(values) != len(import_keys):
227                if len(values) == len(import_keys) + len(info_keys):
228                    msg += "fields from pending file in headline"
229                else:
230                    msg += "%d fields in headline but %d values" % (len(import_keys),len(values))
231                break
232            for k in import_keys:
233                if k in singels:
234                    keys += (k,'%s' % k,values[i],'(duplicate)'),
235                    msg += ("duplicate %s," % k)
236                    keys[singels.index(k)] = (k,'%s' % k,values[singels.index(k)],'(duplicate)')
237                elif k in invalid_keys and not k.startswith(IGNORE):
238                    keys += (k,NO_KEY,values[i],'(invalid)'),
239                else:
240                    keys += (k,k,values[i],''),
241                i += 1
242                singels += k,
243            break
244        return msg,keys
245    ###)
246###)
247
248class ApplicationImport(WAeUPImport):###(
249    name = "application"
250    plural_name = "%ss" % name
251    commit_after = 1000
252
253    def create(self,mapping):###(
254        reg_no = mapping.get('reg_no')
255        msg = ''
256        while True:
257            try:
258                self.applicants_catalog.addRecord(**mapping)
259            except ValueError:
260                msg =  "applicant record with reg_no %s already exists" % reg_no
261            break
262        return reg_no,msg,mapping
263    ###)
264
265    def edit(self,mapping):###(
266        reg_no = mapping.get('reg_no')
267        status = mapping.get('status')
268        msg = ''
269        while True:
270            res = self.applicants_catalog(reg_no = reg_no)
271            if len(res):
272                if res[0].status == 'created' and status != 'created':
273                    msg =  "student object with id %s for %s already created, status cannot be changed" % (res[0].student_id, reg_no)
274                elif status == 'created' and res[0].status != 'created':
275                    msg =  "student object for %s has not yet been created, status cannot be set to 'created'" % (reg_no)
276                else:
277                    self.applicants_catalog.modifyRecord(**mapping)
278            else:
279                msg =  "applicant record with reg_no %s does not exist" % reg_no
280            break
281        return reg_no,msg,mapping
282    ###)
283
284###)
285
286class CertificateImport(WAeUPImport):###(
287    name = "certificate"
288    plural_name = "%ss" % name
289    commit_after = 100000
290
291    def create(self,mapping):###(
292        if getattr(self,'_v_certificate_list',None) is None:
293            self._v_certificate_list = []
294        if getattr(self,'_v_department_certificates',None) is None:
295            departments = self.portal_catalog(portal_type = "Department")
296            self._v_department_certificates = {}
297            for department  in departments:
298                certificates_container = getattr(department.getObject(),"certificates",None)
299                self._v_department_certificates[department.getId] = {'container': certificates_container,
300                                                            'certificates': certificates_container.objectIds(),
301                                                            }
302        department_id = mapping['department_code']
303        msg = ''
304        certificate_id = mapping.get('code')
305        while True:
306            department_certificates = self._v_department_certificates.get(department_id,None)
307            if department_certificates is None:
308                msg =  "No Department with ID: %s" % department_id
309                break
310            certificates_container = department_certificates['container']
311            certificates = department_certificates['certificates']
312            if certificate_id in self._v_certificate_list:
313                msg =  "Duplicate Certificate ID: %s" % department_id
314                break
315            if certificate_id in certificates:
316                msg =  "Duplicate Certificate ID: %s" % department_id
317                break
318            try:
319                certificates_container.invokeFactory('Certificate', certificate_id)
320            except BadRequest,E:
321                msg =  "%s" % E
322                break
323            self._v_certificate_list.append(certificate_id)
324            certificate = getattr(certificates_container,certificate_id)
325            certificate.getContent().edit(mapping=mapping)
326            break
327        return certificate_id,msg,mapping
328    ###)
329
330    def edit(self,mapping):###(
331        certificate_id = mapping.get('code')
332        res = self.portal_catalog(id=certificate_id)
333        msg = ''
334        while True:
335            if not res:
336                msg =  "no certificate with id: %s" % certificate_id
337                break
338            c = res[0].getObject()
339            c.getContent().edit(mapping=mapping)
340            break
341        return certificate_id,msg,mapping
342    ###)
343###)
344
345class CourseImport(WAeUPImport):###(
346    name = "course"
347    plural_name = "%ss" % name
348    commit_after = 1000
349
350    def create(self,mapping):###(
351        if getattr(self,'_v_course_list',None) is None:
352            self._v_course_list = []
353        if getattr(self,'_v_department_courses',None) is None:
354            departments = self.portal_catalog(portal_type = "Department")
355            self._v_department_courses = {}
356            for department in departments:
357                courses_container = getattr(department.getObject(),"courses",None)
358                if courses_container is not None:
359                    self._v_department_courses[department.getId] = {'container': courses_container,
360                                                                    'courses': courses_container.objectIds(),
361                                                                   }
362        department_id = mapping['department_code']
363        course_id = mapping.get('code','')
364        msg = ''
365        while True:
366            department_courses = self._v_department_courses.get(department_id,None)
367            if department_courses is None:
368                msg =  "no department with id: %(department_id)s" % vars()
369                break
370            courses_container = department_courses['container']
371            courses = department_courses['courses']
372            if course_id in self._v_course_list:
373                msg =  "duplicate course id: %(course_id)s" % vars()
374                break
375            if course_id in courses:
376                msg =  "course %(course_id)s already exists in department %(department_id)s" % vars()
377                break
378            try:
379                courses_container.invokeFactory('Course', course_id)
380            except BadRequest,E:
381                msg =  "%s" % E
382                break
383            self._v_course_list.append(course_id)
384            course = getattr(courses_container,course_id)
385            course.getContent().edit(mapping=mapping)
386            break
387        return course_id,msg,mapping
388    ###)
389
390    def edit(self,mapping): ###(
391        course_id = mapping.get('code','')
392        course = self.courses_catalog.getRecordByKey(course_id)
393        msg = ''
394        while True:
395            if course is None:
396                msg =  "no course with id: %s" % course_id
397                break
398            course_object = getattr(getattr(getattr(getattr(self.academics_folder,course.faculty),
399                                    course.department),
400                                    'courses'),
401                                    course_id)
402            course_object.getContent().edit(mapping=mapping)
403            break
404        return course_id,msg,mapping
405    ###)
406
407    def remove(self,mapping): ###(
408        course_id = mapping.get('code','')
409        course = self.courses_catalog.getRecordByKey(course_id)
410        msg = ''
411        while True:
412            if course is None:
413                msg =  "no course with id: %s" % course_id
414                break
415            courses = getattr(getattr(getattr(self.academics_folder,course.faculty),
416                                    course.department),
417                                    'courses')
418            courses.manage_delObjects((course_id),)     
419            break
420        return course_id,msg,mapping
421    ###)   
422   
423###)
424
425class CourseResultImport(WAeUPImport):###(
426    """ CourseresultImport """
427    name = "course_result"
428    plural_name = "%ss" % name
429    commit_after = 1000000
430    required_modes = ('create','edit','remove')
431
432    def create(self,mapping):###(
433        students_folder = self.portal_url.getPortalObject().campus.students
434        if getattr(self,'_v_courses',None) is None:
435            res = self.courses_catalog()
436            self._v_courses = {}
437            for brain in res:
438                self._v_courses[brain.code] = brain
439        if getattr(self,'_v_level_created',None) is None:
440            self._v_level_created = []
441        if getattr(self,'_v_student_study_course',None) is None:
442            self._v_student_study_course = {}
443        msg = ''
444        key = ''
445        matric_no = mapping.get('matric_no','')
446        id = mapping.get('id','')
447        while True:
448            course_id = mapping.get('code')
449            if course_id not in self._v_courses.keys():
450                msg = "no course with id: %s" % course_id
451                break
452            result = self.findStudent('create',student_id=id,matric_no=matric_no)
453            msg = result['msg']
454            if msg:
455                break
456            student_record = result['student_record']
457            student_id = mapping['student_id']  = student_record.id
458            level_id = mapping.get('level_id','')
459            code = mapping.get('code','')
460            level_ident = "%(student_id)s_%(level_id)s" % vars()
461            if level_ident not in self._v_level_created:
462                context = self._v_student_study_course.get(student_id,None)
463                if context is None:
464                    try:
465                        context = getattr(getattr(students_folder,
466                                                "%(student_id)s" % vars()),
467                                        'study_course')
468                        self._v_student_study_course[student_id] = context
469                    except:
470                        msg = "could not create level %(level_id)s for %(student_id)s" % vars()
471                        break
472                if level_id not in context.objectIds():
473                    context.invokeFactory('StudentStudyLevel',"%(level_id)s" % vars())
474                    level = getattr(context,"%(level_id)s" % vars())
475                    self.portal_workflow.doActionFor(level,'open')
476                    session_id = mapping.get('session_id','')
477                    if session_id:
478                        level.getContent().edit(mapping={'session': "%s" % session_id,})
479                    self.portal_workflow.doActionFor(level,'close')
480                    self._v_level_created += level_ident,
481            mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % vars()
482            #overwrite semester and credits in create mode
483            for k in ('semester','credits',):
484                mapping[k] = getattr(self._v_courses[course_id],k)
485            try:
486                self.course_results.addRecord(**mapping)
487            except ValueError:
488                msg = "course result already exists: %s" % key
489            break
490        return key,msg,mapping
491    ###)
492
493    def edit(self,mapping): ###(
494        msg = ''
495        key = ''
496        matric_no = mapping.get('matric_no','')
497        id = mapping.get('id','')
498        while True:
499            result = self.findStudent('edit',student_id=id,matric_no=matric_no)
500            msg = result['msg']
501            if msg:
502                break
503            student_record = result['student_record']
504            student_id = student_record.id
505            level_id = mapping.get('level_id','')
506            code = mapping.get('code','')
507            #code = mapping['code']
508            mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % vars()
509            if self.course_results.getRecordByKey(key) is None:
510                msg =  "no course result with key %(key)s" % vars()
511                break
512            self.course_results.modifyRecord(**mapping)
513            break
514        return key,msg,mapping
515    ###)
516
517    def remove(self,mapping):###(
518        key = ''
519        msg = ''
520        matric_no = mapping.get('matric_no','')
521        id = mapping.get('id','')
522        while True:
523            result = self.findStudent('edit',student_id=id,matric_no=matric_no)
524            msg = result['msg']
525            if msg:
526                break
527            student_record = result['student_record']
528            student_id = student_record.id
529            level_id = mapping.get('level_id','')
530            code = mapping.get('code','')
531            key = "%(student_id)s|%(level_id)s|%(code)s" % vars()
532            if self.course_results.getRecordByKey(key) is None:
533                msg =  "no course result with key %(key)s" % vars()
534                break
535            self.course_results.deleteRecord(key)
536            break
537        return key,msg,mapping
538    ###)
539###)
540
541class CertificateCourseImport(WAeUPImport):###(
542    name = "certificate_course"
543    plural_name = "%ss" % name
544    commit_after = 1000
545    required_modes = ('create','edit')
546
547    def create(self,mapping):
548        if getattr(self,'_v_courses',None) is None:
549            res = self.courses_catalog()
550            self._v_courses= [course.code for course in res]
551        if getattr(self,'_v_ceritficates',None) is None:
552            res = self.portal_catalog(portal_type = "Certificate")
553            self._v_certificates = {}
554            for cert in res:
555                self._v_certificates[cert.getId] = cert.getObject()
556        msg = ''
557        while True:
558            certificate_course_id = mapping.get('code')
559            if certificate_course_id not in self._v_courses:
560                msg =  "no course with id: %s" % certificate_course_id
561                break
562            cert_id = mapping['certificate_code']
563            cert = self._v_certificates.get(cert_id,None)
564            if cert is None:
565                msg =  "no certificate with id: %s" % cert_id
566                break
567            level_id = mapping.get('level')
568            level = getattr(cert,level_id,None)
569            if level is None:
570                cert.invokeFactory('StudyLevel', level_id)
571                level = getattr(cert,level_id,None)
572            elif hasattr(level,certificate_course_id):
573                msg =  "duplicate certificate course id: %(certificate_course_id)s " % vars()
574                msg += "in %(cert_id)s/ %(level_id)s" % vars()
575                break
576            level.invokeFactory('CertificateCourse', certificate_course_id)
577            c = getattr(level,certificate_course_id)
578            c.getContent().edit(mapping=mapping)
579            break
580        return certificate_course_id,msg,mapping
581    ###)
582
583class DepartmentImport(WAeUPImport):###(
584    name = "department"
585    plural_name = "%ss" % name
586    commit_after = 1000
587
588    def create(self,mapping):###(
589        "create a department in the correct faculty"
590        faculty_id = mapping['faculty_code']
591        msg = ''
592        if getattr(self,'_v_faculties',None) is None:
593            res = self.portal_catalog(portal_type = "Faculty")
594            self._v_faculties = {}
595            for f in res:
596                self._v_faculties[f.getId] = f.getObject()
597        department_id = mapping.get('code','')
598        while True:
599            faculty = self._v_faculties.get(faculty_id,None)
600            if faculty is None:
601                msg =  "no faculty with id: %s" % faculty_id
602                break
603            else:
604                d = getattr(faculty,department_id,None)
605                if d is None or d.portal_type == "Faculty":
606                    try:
607                        faculty.invokeFactory('Department', department_id)
608                    except BadRequest,E:
609                        msg =  "%s" % E
610                        break
611                    d = getattr(faculty,department_id)
612                    d.invokeFactory('CoursesFolder','courses')
613                    courses = getattr(d,'courses')
614                    dict = {'Title': 'Courses'}
615                    courses.getContent().edit(mapping=dict)
616                    d.invokeFactory('CertificatesFolder','certificates')
617                    certificates = getattr(d,'certificates')
618                    dict = {'Title': 'Certificates'}
619                    certificates.getContent().edit(mapping=dict)
620                    d.getContent().edit(mapping=mapping)
621            break
622        return department_id,msg,mapping
623    ###)
624
625    def edit(self,mapping): ###(
626        "edit a department in the correct faculty"
627        academics_folder = self.portal_url.getPortalObject().campus.academics
628        faculty_id = mapping['faculty_code']
629        department_id = mapping.get('code','')
630        msg = ''
631        while True:
632            try:
633                d = getattr(getattr(academics_folder,faculty_id),department_id,None)
634            except KeyError:
635                msg =  "department %s or faculty %s wrong" % (department_id,faculty_id)
636                break
637            if d is None or d.portal_type == "Faculty":
638                msg =  "department %s not found" % (department_id)
639                break
640            d.getContent().edit(mapping=mapping)
641            break
642        return department_id,msg,mapping
643    ###)
644###)
645
646class FacultyImport(WAeUPImport):###(
647    name = "faculty"
648    plural_name = "faculties"
649    commit_after = 100
650   
651
652    def create(self,mapping): ###(
653        "create a faculty"
654        academics_folder = self.portal_url.getPortalObject().campus.academics
655        faculty_id = mapping.get('code','')
656        msg = ''
657        while True:
658            if faculty_id in academics_folder.objectIds():
659                msg =  "faculty with id: %s exists" % faculty_id
660                break
661            try:
662                academics_folder.invokeFactory('Faculty', faculty_id)
663            except BadRequest,E:
664                msg =  "%s" % E
665                break
666            f = getattr(academics_folder,faculty_id,None)
667            f.getContent().edit(mapping=mapping)
668            break
669        return faculty_id,msg,mapping
670        ###)
671
672    def edit(self,mapping): ###(
673        "edit a faculty"
674        academics_folder = self.portal_url.getPortalObject().campus.academics
675        faculty_id = mapping['code']
676        msg = ''
677        while True:
678            f = getattr(academics_folder,faculty_id,None)
679            if f is None:
680                msg =  "faculty with id: %s does not exist" % faculty_id
681            f.getContent().edit(mapping=mapping)
682            break
683        return faculty_id,msg,mapping
684    ###)
685###)
686
687class StudentImport(WAeUPImport):###(
688    name = "student"
689    plural_name = "%ss" % name
690    commit_after = 100
691
692    field2types_student = {   ###(
693                      'StudentApplication':
694                          {'id': 'application',
695                           #'title': 'Application Data',
696                           'wf_transition_return': 'close',
697                           'wf_transition_admit': 'remain',
698                           'wf_transition_graduate': 'close',
699                           'wf_transition_pay_school_fee': 'close',
700                           'wf_transition_validate_courses': 'close',
701                           'fields':
702                             ('jamb_reg_no',
703                              'entry_mode',
704                              'entry_session',
705                              'jamb_score',
706                              'app_email',
707                              'jamb_age',
708                              'jamb_state',
709                              'jamb_lga',
710                              'jamb_sex',
711                              )
712                              },
713                      #'StudentPume':
714                      #    {'id': 'pume',
715                      #     'title': 'Pume Data',
716                      #     'wf_transition_return': 'close',
717                      #     'wf_transition_admit': 'close',
718                      #     'fields':
719                      #       ('pume_score',
720                      #        )
721                      #        },
722                      'StudentClearance':
723                          {'id': 'clearance',
724                           #'title': 'Clearance/Eligibility Record',
725                           'wf_transition_return': 'close',
726                           'wf_transition_admit': 'remain',
727                           'wf_transition_graduate': 'close',
728                           'wf_transition_pay_school_fee': 'close',
729                           'wf_transition_validate_courses': 'close',
730                           'fields':
731                             ('matric_no',
732                              'nationality',
733                              'lga',
734                              'birthday',
735                              )
736                              },
737                         'StudentPersonal':
738                          {'id': 'personal',
739                           #'title': 'Personal Data',
740                           'wf_transition_return': 'open',
741                           'wf_transition_admit': 'remain',
742                           'wf_transition_graduate': 'close',
743                           'wf_transition_pay_school_fee': 'open',
744                           'wf_transition_validate_courses': 'open',
745                           'fields':
746                             ('firstname',
747                              'middlename',
748                              'lastname',
749                              'sex',
750                              'email',
751                              'phone',
752                              'perm_address',
753                              )
754                              },
755                         'StudentStudyCourse':
756                          {'id': 'study_course',
757                           #'title': 'Study Course',
758                           'wf_transition_return': 'open',
759                           'wf_transition_admit': 'remain',
760                           'wf_transition_graduate': 'close',
761                           'wf_transition_pay_school_fee': 'open',
762                           'wf_transition_validate_courses': 'open',
763                           'fields':
764                             ('study_course',
765                              'current_level',
766                              'current_session',
767                              'current_mode',  #is no longer used and visible but can still be imported
768                              'current_verdict',
769                              'previous_verdict',
770                              )
771                              },
772                         # 'StudentStudyLevel':
773                         #  {'id': 'current_level',
774                         #   'title': '',
775                         #   'wf_transition_return': 'open',
776                         #   'wf_transition_admit': 'remain',
777                         #   'fields':
778                         #     ('verdict',
779                         #      'session',
780                         #      )
781                         #      },
782                         'PaymentsFolder':
783                          {'id': 'payments',
784                           #'title': 'Payments',
785                           'wf_transition_return': 'open',
786                           'wf_transition_admit': 'open',
787                           'wf_transition_graduate': 'close',
788                           'wf_transition_pay_school_fee': 'open',
789                           'wf_transition_validate_courses': 'open',
790                           'fields':
791                             ()
792                              },
793                         }
794    ###)
795
796    def create(self,mapping): ###(
797        "create student records due import"
798        logger = logging.getLogger('WAeUPImport.StudentImport.create')
799        students_folder = self.portal_url.getPortalObject().campus.students
800        jamb_reg_no = mapping.get('jamb_reg_no',None)
801        matric_no = mapping.get('matric_no',None)
802        entry_mode = mapping.get('entry_mode',None)
803        msg = ''
804        student_id = mapping.get('id',None)
805        while True:
806            if student_id:
807                msg = "student_id must not be specified in create mode"
808                break
809            if jamb_reg_no and not entry_mode == 'transfer':
810                res = self.students_catalog(jamb_reg_no = jamb_reg_no)
811                if res:
812                    msg = "jamb_reg_no already assigned to student %s" % res[0].id
813                    break
814            if matric_no:
815                res = self.students_catalog(matric_no = matric_no)
816                if res:
817                    msg = "matric_no already assigned to student %s" % res[0].id
818                    break
819            if not matric_no and not jamb_reg_no:
820                msg = "jamb_reg_no or matric_no must be specified"
821                break
822            student_id = self.waeup_tool.generateStudentId('?')
823            students_folder.invokeFactory('Student', student_id)
824            student_obj = getattr(students_folder,student_id)
825            f2t = self.field2types_student
826            d = {}
827            transition = mapping.get('reg_transition','admit')
828            if transition not in ('admit','return','pay_school_fee','validate_courses'):
829                msg = "no valid transition provided"
830                break
831            for pt in f2t.keys():
832                student_obj.invokeFactory(pt,f2t[pt]['id'])
833                sub_obj = getattr(student_obj,f2t[pt]['id'])
834                sub_doc = sub_obj.getContent()
835                #d['Title'] = f2t[pt]['title']
836                for field in f2t[pt]['fields']:
837                    d[field] = mapping.get(field,'')
838
839                if pt == "StudentApplication":
840                    #d['jamb_sex']  = 'M'
841                    #if mapping.get('sex'):
842                    #    d['jamb_sex']  = 'F'
843                    d['jamb_firstname'] = mapping.get('firstname',None)
844                    d['jamb_middlename'] = mapping.get('middlename',None)
845                    d['jamb_lastname'] = mapping.get('lastname',None)
846
847                # if pt == "StudyCourse":
848                #     for von,zu in (('entry_mode','current_mode'),
849                #                    ('entry_session','current_session')):
850                #         if mapping.get(zu,None) is None and mapping.get(von,None) is not None:
851                #             d[zu] = mapping[von]
852                sub_doc.edit(mapping = d)
853
854                #import pdb;pdb.set_trace()
855                new_state = f2t[pt]['wf_transition_%(transition)s' % vars()]
856                if new_state != "remain":
857                    self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
858            self.portal_workflow.doActionFor(student_obj,transition)
859            student_obj.manage_setLocalRoles(student_id, ['Owner',])
860            mapping['id'] = student_id
861            break
862        return student_id,msg,mapping
863    ###)
864
865    def remove(self,mapping): ###(
866        "remove student records due import"
867        logger = logging.getLogger('WAeUPImport.StudentImport.remove')
868        students_folder = self.portal_url.getPortalObject().campus.students
869        stdir = self.portal_directories.students
870        student_id = mapping.get('id',None)
871        msg = ''
872        export_file = "%s/export/students_removed.csv" % (i_home)
873       
874        #toexport = {
875        #
876        #            'personal': ('firstname',
877        #                         'middlename',
878        #                         'lastname',
879        #                         'perm_address',
880        #                         ),
881        #            'clearance': ('lga',
882        #                          'birthday',
883        #                         )
884        #
885        #           }
886
887        sub_types = ['StudentApplication','StudentClearance','StudentPersonal','StudentStudyCourse']
888        non_image_keys = {}
889        for i in sub_types:
890            pt_ob = getattr(self.types_tool,i)
891            sub_schemas = pt_ob.schemas
892            for i in sub_schemas:
893                if i.startswith('student_'):
894                    schema = getattr(self.schema_tool,i)
895                    field_id = i.replace('student_','')
896                    non_image_keys[field_id] = [key for key in schema.keys()
897                                     if schema[key].meta_type != "CPS Image Field"]       
898        toexport = non_image_keys
899
900        #import pdb;pdb.set_trace()   
901        while True:
902            if hasattr(students_folder,student_id):
903                # begin export
904                line = []
905                fields = []
906                for f in self.students_catalog.schema():
907                    fields.append(f)               
908                for k in toexport.keys():
909                    for f in toexport[k]:
910                        fields.append(f)
911                if True:    #not os.path.exists(export_file):       
912                    #headline = ','.join(fields).replace('level','current_level')
913                    headline = ','.join(fields)
914                    headline = headline + ',password'
915                    open(export_file,"a").write(headline +'\n')
916                format = '"%(' + ')s","%('.join(fields) + ')s"'
917                format = format + ',"%(password)s"'
918                res = self.students_catalog(id = student_id)
919                student = res[0]
920                student_obj = getattr(students_folder,student_id)
921                d = student.getFormattedStudentEntry(student)
922                for k in toexport.keys()[0:]:
923                    try:
924                        object = getattr(student_obj,k)
925                        object_doc = object.getContent()
926                    except:
927                        continue
928                    for f in toexport[k]:
929                        d[f] = getattr(object_doc,f,'')
930                if hasattr(stdir, student_id):
931                    d['password'] = self.waeup_tool.getCredential(student_id)
932                    stdir.deleteEntry(student_id)
933                self.waeup_tool.removePictureFolder(student_id)       
934                line.append(format % d)
935                open(export_file,"a").write('\n'.join(line) +'\n')
936                self.course_results.getExportRemoveAllCourses(student_id = student_id, export = True, remove = True)
937                # end export
938                students_folder.manage_delObjects((student_id),)         
939            else:
940                msg = "Student object not found"
941                break
942     
943            break
944        return student_id,msg,mapping     
945
946
947    def edit(self,mapping): ###(
948        "edit student records due import"
949        wftool = self.portal_workflow
950        logger = logging.getLogger('WAeUPImport.StudentImport.edit')
951        students_folder = self.portal_url.getPortalObject().campus.students
952        student_id = mapping.get('id',None)
953        jamb_reg_no = mapping.get('jamb_reg_no',None)
954        matric_no = mapping.get('matric_no',None)
955        editable_keys = mapping.keys()
956        msg = ''
957        while True:
958            if student_id:
959                res = self.students_catalog(id = student_id)
960                if not res:
961                    msg = "no student with id %s" % student_id
962                    break
963                student_record = res[0]
964                if matric_no and student_record.matric_no:
965                    if  matric_no != student_record.matric_no and not matric_no == 'transferred':
966                        res = self.students_catalog(matric_no = matric_no)
967                        if res:
968                            msg = "matric_no already assigned to student %s" % res[0].id
969                            break
970                        msg = "old matric_no %s overwritten with %s" % (student_record.matric_no,matric_no)
971                        #logger.info("%s, old matric_no %s overwritten with %s" % (student_record.id,student_record.matric_no,matric_no))
972                if jamb_reg_no and student_record.jamb_reg_no:
973                    if jamb_reg_no != student_record.jamb_reg_no:
974                        res = self.students_catalog(jamb_reg_no = jamb_reg_no)
975                        if res:
976                            msg = "jamb_reg_no already assigned to student %s" % res[0].id
977                            break
978                        msg = "old jamb_reg_no %s overwritten with %s" % (student_record.jamb_reg_no,jamb_reg_no)
979                        #logger.info("%s, old reg_no %s overwritten with %s" % (student_record.id,student_record.jamb_reg_no,jamb_reg_no))
980            elif jamb_reg_no:
981                res = self.students_catalog(jamb_reg_no = jamb_reg_no)
982                if not res:
983                    msg = "no student with jamb_reg_no %s" % jamb_reg_no
984                    break
985                student_record = res[0]
986                editable_keys.remove('jamb_reg_no')
987            elif matric_no:
988                res = self.students_catalog(matric_no = matric_no)
989                if not res:
990                    msg = "no student with matric_no %s" % matric_no
991                    break
992                student_record = res[0]
993                editable_keys.remove('matric_no')
994            student_id = student_record.id
995            student_obj = getattr(students_folder,student_id)
996            f2t = self.field2types_student
997            d = {}
998            any_change = False
999            #special treatment for StudentStudyLevel
1000            d['verdict']  = mapping.get('current_verdict','')
1001            d['session']  = mapping.get('current_session','')
1002            current_level = mapping.get('current_level','')
1003            transition = mapping.get('reg_transition',None)
1004            # the validate_courses import transition is not really useful because it does not execute validate_courses.py
1005            if transition and transition not in ('admit','return','graduate','pay_school_fee','validate_courses'):
1006                msg = "no valid transition provided"
1007                break     
1008            while d['session'] and d['verdict'] and current_level:
1009                sub_obj = getattr(student_obj,'study_course',None)
1010                if sub_obj is None:
1011                    break
1012                level_obj = getattr(sub_obj,current_level,None)
1013                if  level_obj is None:
1014                    break
1015                any_change = True
1016                level_obj.getContent().edit(mapping = d)
1017                try:
1018                    wftool.doActionFor(level_obj,'close')
1019                except:
1020                    pass
1021                break
1022           
1023            for pt in f2t.keys():
1024                #if pt == "StudentApplication":
1025                #    d['jamb_sex']  = 'M'
1026                #    if mapping.get('sex'):
1027                #        d['jamb_sex']  = 'F'
1028                intersect = set(f2t[pt]['fields']).intersection(set(editable_keys))
1029                #import pdb;pdb.set_trace()
1030                object_id = f2t[pt]['id']
1031                sub_obj = getattr(student_obj,object_id,None)
1032                if intersect and pt not in ('StudentStudyLevel',):
1033                    if sub_obj is None:
1034                        try:
1035                            student_obj.invokeFactory(pt,object_id)
1036                        except:
1037                            continue
1038                        sub_obj = getattr(student_obj,object_id)
1039                        #if f2t[pt]['title'] != '':
1040                        #    d['Title'] = f2t[pt]['title']
1041                    sub_doc = sub_obj.getContent()
1042                    for field in intersect:
1043                        changed = False
1044                        if getattr(sub_doc,field,None) != mapping.get(field,''):
1045                            any_change = True
1046                            changed = True
1047                            d[field] = mapping.get(field,'')
1048                        if changed:
1049                            sub_doc.edit(mapping = d)
1050                if transition:
1051                    new_state = f2t[pt]['wf_transition_%(transition)s' % vars()]
1052                    if new_state != "remain":
1053                        try:
1054                            self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1055                        except:
1056                            pass
1057            if transition:
1058                try:
1059                    self.portal_workflow.doActionFor(student_obj,transition)
1060                except:
1061                    msg = "reg_transition not allowed"
1062            break
1063        return student_id,msg,mapping
1064    ###)
1065###)
1066
1067class StudentStudyLevelImport(WAeUPImport):###(
1068    """ StudentStudyLevelImport """
1069    name = "student_study_level"
1070    plural_name = "%ss" % name
1071    commit_after = 1000000
1072    required_modes = ('create',)
1073
1074    def create(self,mapping): ###(
1075        "edit student levels and create StudentStudyLevel object if not existent"
1076        wftool = self.portal_workflow
1077        logger = logging.getLogger('WAeUPTool.mass_create_level')
1078        students_folder = self.portal_url.getPortalObject().campus.students
1079        student_id = mapping.get('id',None)
1080        matric_no = mapping.get('matric_no',None)
1081        editable_keys = mapping.keys()
1082        key = ''
1083        msg = ''
1084        while True:
1085            result = self.findStudent('create',student_id=student_id,matric_no=matric_no)
1086            msg = result['msg']
1087            if msg:
1088                break
1089            student_record = result['student_record']
1090            student_id = student_record.id
1091            mapping['id'] = student_id
1092            session = mapping.get('session','')
1093            level = key = mapping.get('code','')
1094            if not level.isdigit():
1095                msg = 'student %s: imported level is empty' % (student_id,)
1096                break
1097            study_course_obj = getattr(getattr(students_folder,student_id),'study_course',None)
1098            if study_course_obj is None:
1099                msg = 'student %s: no study_course object' % student_id
1100                break
1101            level_obj = getattr(study_course_obj,level,None)
1102            if  level_obj is None:
1103                # The only difference to the edit method is that we create a StudentStudyLevel object
1104                try:
1105                    study_course_obj.invokeFactory('StudentStudyLevel',"%s" % level)
1106                    level_obj = getattr(context,"%s" % level)
1107                except:
1108                    continue
1109            level_obj.getContent().edit(mapping = mapping)
1110            level_review_state = wftool.getInfoFor(level_obj,'review_state',None)
1111            if level_review_state != "closed":
1112                wftool.doActionFor(level_obj,'close')
1113            break
1114        return key,msg,mapping
1115    ###)
1116
1117    def edit(self,mapping): ###(
1118        "edit student levels"
1119        wftool = self.portal_workflow
1120        logger = logging.getLogger('WAeUPTool.mass_edit_level')
1121        students_folder = self.portal_url.getPortalObject().campus.students
1122        student_id = mapping.get('id',None)
1123        matric_no = mapping.get('matric_no',None)
1124        key = ''
1125        msg = ''
1126        while True:
1127            result = self.findStudent('create',student_id=student_id,matric_no=matric_no)
1128            msg = result['msg']
1129            if msg:
1130                break
1131            student_record = result['student_record']
1132            student_id = student_record.id
1133            mapping['id'] = student_id
1134            session = mapping.get('session','')
1135            level = key = mapping.get('code','')
1136            #import pdb;pdb.set_trace()
1137            if not level.isdigit():
1138                msg = 'student %s: imported level is empty' % (student_id,)
1139                break
1140            study_course_obj = getattr(getattr(students_folder,student_id),'study_course',None)
1141            if study_course_obj is None:
1142                msg = 'student %s: no study_course object' % student_id
1143                break
1144            level_obj = getattr(study_course_obj,level,None)
1145            if  level_obj is None:
1146                msg = 'student %s: no study_level object for level %s' % (student_id,level)
1147                break
1148            level_obj.getContent().edit(mapping = mapping)
1149            break
1150        return key,msg,mapping
1151    ###)
1152###)
1153
1154class VerdictImport(WAeUPImport):###(
1155    """ VerdictImport """
1156    name = "verdict"
1157    plural_name = "%ss" % name
1158    commit_after = 1000
1159    required_modes = ('create','edit')
1160
1161    def create(self,mapping): ###(
1162        "edit student verdicts and create StudentStudyLevel object if not existent"
1163        wftool = self.portal_workflow
1164        logger = logging.getLogger('WAeUPTool.mass_edit_verdict')
1165        students_folder = self.portal_url.getPortalObject().campus.students
1166        student_id = mapping.get('id',None)
1167        matric_no = mapping.get('matric_no',None)
1168        editable_keys = mapping.keys()
1169        key = ''
1170        while True:
1171            result = self.findStudent('create',student_id=student_id,matric_no=matric_no)
1172            #student_record,msg = self.getStudentRecord(mapping)
1173            msg = result['msg']
1174            if msg:
1175                break
1176            student_record = result['student_record']
1177            student_id = student_record.id
1178            mapping['id'] = student_id
1179            d = {}
1180            #import pdb;pdb.set_trace()
1181            any_change = False
1182            #special treatment for StudentStudyLevel
1183            current_session = d['session'] = mapping.get('current_session','')
1184            if current_session and student_record.session != current_session:
1185                msg = 'student %s: imported session %s does not match current_session %s' % (student_id,
1186                                                                                            current_session,
1187                                                                                            student_record.session)
1188                break
1189            current_level = mapping.get('current_level','')
1190            if not current_level.isdigit():
1191                msg = 'student %s: imported level is empty' % (student_id,)
1192                break
1193            if current_level and student_record.level != current_level:
1194                msg = 'student %s: imported level %s does not match current_level %s' % (student_id,
1195                                                                                        current_level,
1196                                                                                        student_record.level)
1197                break
1198            student_review_state =  student_record.review_state
1199            if student_review_state == 'deactivated':
1200                msg = "student %s in review_state %s" % (student_id, student_review_state)
1201                break
1202            if student_review_state not in ('courses_validated','returning'):
1203                msg = "student %s in wrong review_state %s" % (student_id, student_review_state)
1204                break
1205            student_obj = getattr(students_folder,student_id)
1206            # f2t = self.field2types_student
1207            study_course_obj = getattr(student_obj,'study_course',None)
1208            if study_course_obj is None:
1209                msg = 'student %s: no study_course object' % student_id
1210                break
1211            level_obj = getattr(study_course_obj,current_level,None)
1212
1213            if  level_obj is None:
1214                # The only difference to the edit method is that we create a StudentStudyLevel object
1215                try:
1216                    study_course_obj.invokeFactory('StudentStudyLevel',"%s" % current_level)
1217                    level_obj = getattr(context,"%s" % current_level)
1218                    level_obj.portal_workflow.doActionFor(level,'open')
1219                except:
1220                    continue
1221                #msg = 'student %s: no study_level object for level %s' % (student_id,
1222                #                                                                current_level)
1223                #break
1224
1225            verdict = d['verdict'] = d['current_verdict']  = mapping.get('current_verdict','')
1226
1227            #if verdict == student_record.verdict:
1228            #    msg = 'student %s: verdict already set to %s' % (student_id,
1229            #                                                            verdict)
1230
1231            level_review_state = wftool.getInfoFor(level_obj,'review_state',None)
1232            if level_review_state != "closed":
1233                wftool.doActionFor(level_obj,'close')
1234                # msg = 'student %s: level %s is not closed' % (student_id,
1235                #                                                      current_level)
1236
1237            study_course_obj.getContent().edit(mapping = d)
1238            level_obj.getContent().edit(mapping = d)
1239            if student_review_state != "returning":
1240                wftool.doActionFor(student_obj,'return')
1241            # try:
1242            #     wftool.doActionFor(level_obj,'close')
1243            # except:
1244            #     pass
1245            break
1246        return student_id,msg,mapping
1247    ###)
1248
1249
1250    def edit(self,mapping): ###(
1251        "edit student verdicts"
1252        wftool = self.portal_workflow
1253        logger = logging.getLogger('WAeUPTool.mass_edit_verdict')
1254        students_folder = self.portal_url.getPortalObject().campus.students
1255        student_id = mapping.get('id',None)
1256        matric_no = mapping.get('matric_no',None)
1257        editable_keys = mapping.keys()
1258        key = ''
1259        while True:
1260            result = self.findStudent('edit',student_id=student_id,matric_no=matric_no)
1261            #student_record,msg = self.getStudentRecord(mapping)
1262            msg = result['msg']
1263            if msg:
1264                break
1265            student_record = result['student_record']
1266            key_used = result['key_used']
1267            if key_used in editable_keys:
1268                editable_keys.remove(key_used)
1269            student_id = student_record.id
1270            mapping['id'] = student_id
1271            d = {}
1272            #import pdb;pdb.set_trace()
1273            any_change = False
1274            #special treatment for StudentStudyLevel
1275            current_session = d['session'] = mapping.get('current_session','')
1276            if current_session and student_record.session != current_session:
1277                msg = 'student %s: imported session %s does not match current_session %s' % (student_id,
1278                                                                                            current_session,
1279                                                                                            student_record.session)
1280                break
1281            current_level = mapping.get('current_level','')
1282            if not current_level.isdigit():
1283                msg = 'student %s: imported level is empty' % (student_id,)
1284                break
1285            if current_level and student_record.level != current_level:
1286                msg = 'student %s: imported level %s does not match current_level %s' % (student_id,
1287                                                                                        current_level,
1288                                                                                        student_record.level)
1289                break
1290            student_review_state =  student_record.review_state
1291            if student_review_state == 'deactivated':
1292                msg = "student %s in review_state %s" % (student_id, student_review_state)
1293                break
1294            if student_review_state not in ('courses_validated','returning'):
1295                msg = "student %s in wrong review_state %s" % (student_id, student_review_state)
1296                break
1297            student_obj = getattr(students_folder,student_id)
1298            # f2t = self.field2types_student
1299            study_course_obj = getattr(student_obj,'study_course',None)
1300            if study_course_obj is None:
1301                msg = 'student %s: no study_course object' % student_id
1302                break
1303            level_obj = getattr(study_course_obj,current_level,None)
1304            if  level_obj is None:
1305                msg = 'student %s: no study_level object for level %s' % (student_id,
1306                                                                                current_level)
1307                break
1308            verdict = d['verdict'] = d['current_verdict']  = mapping.get('current_verdict','')
1309
1310            #if verdict == student_record.verdict:
1311            #    msg = 'student %s: verdict already set to %s' % (student_id,
1312            #                                                            verdict)
1313
1314            level_review_state = wftool.getInfoFor(level_obj,'review_state',None)
1315            if level_review_state != "closed":
1316                wftool.doActionFor(level_obj,'close')
1317                # msg = 'student %s: level %s is not closed' % (student_id,
1318                #                                                      current_level)
1319
1320            study_course_obj.getContent().edit(mapping = d)
1321            level_obj.getContent().edit(mapping = d)
1322            if student_review_state != "returning":
1323                wftool.doActionFor(student_obj,'return')
1324            # try:
1325            #     wftool.doActionFor(level_obj,'close')
1326            # except:
1327            #     pass
1328            break
1329        return student_id,msg,mapping
1330    ###)
1331
1332    def edit_old(self,mapping): ###(
1333        "edit student verdicts"
1334        wftool = self.portal_workflow
1335        logger = logging.getLogger('WAeUPTool.mass_edit_verdict')
1336        students_folder = self.portal_url.getPortalObject().campus.students
1337        student_id = mapping.get('id',None)
1338        matric_no = mapping.get('matric_no',None)
1339        editable_keys = mapping.keys()
1340        key = ''
1341        while True:
1342            msg = ''
1343            if student_id:
1344                student_record = self.students_catalog.getRecordByKey(student_id)
1345                if student_record is None:
1346                    #return '',"no student with id %s" % student_id
1347                    msg = "no student with id %s" % student_id
1348                    break
1349                if matric_no and student_record.matric_no and matric_no != student_record.matric_no:
1350                    msg = 'student %s: matric_no %s does not match %s' % (student_record.id,
1351                                                                          student_record.matric_no,
1352                                                                          matric_no)
1353                    break
1354                mapping['matric_no'] = student_record.matric_no
1355            elif matric_no:
1356                res = self.students_catalog(matric_no = matric_no)
1357                if not res:
1358                    msg = "no student with matric_no %s" % matric_no
1359                    break
1360                student_record = res[0]
1361                editable_keys.remove('matric_no')
1362            else:
1363                msg = "no id or matric_no specified"
1364                break
1365            student_id = student_record.id
1366            mapping['id'] = student_id
1367            d = {}
1368            #import pdb;pdb.set_trace()
1369            any_change = False
1370            #special treatment for StudentStudyLevel
1371            current_session = d['session'] = mapping.get('current_session','')
1372            if current_session and student_record.session != current_session:
1373                msg = 'student %s: imported session %s does not match current_session %s' % (student_id,
1374                                                                                            current_session,
1375                                                                                            student_record.session)
1376                break
1377            current_level = mapping.get('current_level','')
1378            if not current_level.isdigit():
1379                msg = 'student %s: imported level is empty' % (student_id,)
1380                break
1381            if current_level and student_record.level != current_level:
1382                msg = 'student %s: imported level %s does not match current_level %s' % (student_id,
1383                                                                                        current_level,
1384                                                                                        student_record.level)
1385                break
1386            student_review_state =  student_record.review_state
1387            if student_review_state == 'deactivated':
1388                msg = "student %s in review_state %s" % (student_id, student_review_state)
1389                break
1390            if student_review_state not in ('courses_validated','returning'):
1391                msg = "student %s in wrong review_state %s" % (student_id, student_review_state)
1392                break
1393            student_obj = getattr(students_folder,student_id)
1394            # f2t = self.field2types_student
1395            study_course_obj = getattr(student_obj,'study_course',None)
1396            if study_course_obj is None:
1397                msg = 'student %s: no study_course object' % student_id
1398                break
1399            level_obj = getattr(study_course_obj,current_level,None)
1400            if  level_obj is None:
1401                msg = 'student %s: no study_level object for level %s' % (student_id,
1402                                                                                current_level)
1403                break
1404            verdict = d['verdict'] = d['current_verdict']  = mapping.get('current_verdict','')
1405
1406            #if verdict == student_record.verdict:
1407            #    msg = 'student %s: verdict already set to %s' % (student_id,
1408            #                                                            verdict)
1409
1410            level_review_state = wftool.getInfoFor(level_obj,'review_state',None)
1411            if level_review_state != "closed":
1412                wftool.doActionFor(level_obj,'close')
1413                # msg = 'student %s: level %s is not closed' % (student_id,
1414                #                                                      current_level)
1415
1416            study_course_obj.getContent().edit(mapping = d)
1417            level_obj.getContent().edit(mapping = d)
1418            if student_review_state != "returning":
1419                wftool.doActionFor(student_obj,'return')
1420            # try:
1421            #     wftool.doActionFor(level_obj,'close')
1422            # except:
1423            #     pass
1424            break
1425        return student_id,msg,mapping
1426    ###)
1427###)
Note: See TracBrowser for help on using the repository browser.