source: WAeUP_SRP/base/WAeUPImport.py @ 3481

Last change on this file since 3481 was 3481, checked in by Henrik Bettermann, 17 years ago

fix addStudent (fetch dictionary correctly)

remove Title completely (Title was still indexed in portal_catalog)

remove Title method from PaymentsFolder? class

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