#-*- mode: python; mode: fold -*- # (C) Copyright 2005 The WAeUP group # Author: Joachim Schmitz (js@aixtraware.de) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as published # by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # # $Id: WAeUPImport.py 3336 2008-03-14 22:53:14Z henrik $ """The WAeUP Tool Box. """ #from AccessControl import ClassSecurityInfo #from Acquisition import aq_inner #from Acquisition import aq_parent #from Globals import DTMLFile #from Globals import InitializeClass from OFS.SimpleItem import SimpleItem from zExceptions import BadRequest #from Products.CMFCore.utils import getToolByName #from Products.CPSSchemas.DataStructure import DataStructure #from Products.CPSSchemas.DataModel import DataModel #from Products.CPSSchemas.StorageAdapter import MappingStorageAdapter from Products.CMFCore.ActionProviderBase import ActionProviderBase #from Products.CMFCore.permissions import View #from Products.ZCatalog.ZCatalog import ZCatalog #from Products.CMFCore.permissions import ModifyPortalContent #from Products.CMFCore.permissions import ManagePortal from Products.CMFCore.utils import UniqueObject #from Products.CMFCore.URLTool import URLTool from Products.CMFCore.utils import getToolByName from Globals import package_home,INSTANCE_HOME from Products.AdvancedQuery import Eq, Between, Le,In import csv,re,os,sys from shutil import copy2 import DateTime,time import logging p_home = package_home(globals()) i_home = INSTANCE_HOME from utils import makeDigest NO_KEY = '----' IGNORE = 'ignore' class WAeUPImport(UniqueObject, SimpleItem, ActionProviderBase): ###( """ WAeUPImport """ required_modes = ('create',) def __init__(self,waeup_tool): ###( self.students_folder = waeup_tool.portal_url.getPortalObject().campus.students self.member = member = waeup_tool.portal_membership.getAuthenticatedMember() self.import_date = DateTime.DateTime() self.imported_by = str(member) #self.current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S") self.waeup_tool = waeup_tool self.academics_folder = waeup_tool.portal_url.getPortalObject().campus.academics self.schema_tool = getToolByName(waeup_tool, 'portal_schemas') self.layout_tool = getToolByName(waeup_tool, 'portal_layouts') self.portal_workflow = getToolByName(waeup_tool, 'portal_workflow') self.portal_url = getToolByName(waeup_tool, 'portal_url') self.portal_catalog = waeup_tool.portal_catalog self.students_catalog = waeup_tool.students_catalog self.courses_catalog = waeup_tool.courses_catalog self.course_results = waeup_tool.course_results self.applicants_catalog = waeup_tool.applicants_catalog #self.mode = mode # self.import_method = getattr(self, '%s' % mode,None) errors = [] # if self.import_method is None: # errors.append('No importer method %s' % mode) self.pending_path = "%s/import/%s.pending" % (i_home,self.plural_name) self.pending_tmp = "%s/import/%s.pending.tmp" % (i_home,self.plural_name) self.pending_backup = "%s/import/%s.pending.old" % (i_home,self.plural_name) self.pending_fn = os.path.split(self.pending_path)[1] self.imported_path = "%s/import/%s.imported" % (i_home,self.plural_name) self.imported_fn = os.path.split(self.imported_path)[1] iname = "import_%s" % self.name self.logger = logging.getLogger('WAeUPImport.%sImport' % self.plural_name.capitalize()) self.schema = self.schema_tool._getOb(iname,None) #self.pending_schema = self.schema_tool._getOb("%s_pending" % iname,None) self.layout = self.layout_tool._getOb(iname,None) while True: if self.schema is None: errors.append('no schema %s' % iname) # if self.pending_schema is None: # self.pending_schema = self.schema if self.layout is None: errors.append('no such layout %s' % iname) if errors: break self.data_keys = self.schema.keys() self.csv_keys = self.schema.keys() info = {} info['imported_from'] = '' info['import_record_no'] = 0 info['imported_by'] = self.imported_by info['import_date'] = self.import_date.strftime("%d/%m/%y %H:%M:%S") info['error'] = '' self.info = info self.csv_keys.extend(self.info) self.validators = {} for widget in self.layout.keys(): self.validators[widget] = self.layout[widget].validate self.required_keys = {} for mode in self.required_modes: self.required_keys[mode] = [self.layout.getIdUnprefixed(id) for id,widget in self.layout.objectItems() if widget.is_required] break self.init_errors = ','.join(errors) ###) def makeIdLists(self): ###( pending_digests = [] pending = [] # pending_student_ids = [] # pending_matric_nos = [] # pending_reg_ns = [] if os.path.exists(self.pending_path): datafile = open(self.pending_path,"r") reader = csv.reader(datafile) old_headline = reader.next() #datafile.seek(0) pending_csv_reader = csv.DictReader(datafile,old_headline,) #pending_csv_reader.next() # skip headline for item in pending_csv_reader: digest = makeDigest(item,self.data_keys) if digest not in pending_digests: pending_digests += digest, pending += item, datafile.close() #copy2(self.pending_path,self.pending_backup) return pending, pending_digests ###) def checkHeadline(self,headline): ###( """ check the headline of a csv file """ import_keys = [k.strip() for k in headline if not (k.strip().startswith('ignore') or k.strip() in self.info.keys())] # import_keys = [k.strip() for k in headline if not (k.strip() in self.info.keys())] diff2schema = set(import_keys).difference(set(self.schema.keys())) diff2layout = set(import_keys).difference(set(self.layout.keys())) #if diff2schema and diff2schema != set(['id',]): if diff2schema: return list(diff2schema) return [] ###) def getHeadlineFields(self,headline,values): ###( """ check the headline of a csv file """ # import_keys = [k.strip() for k in headline if not (k.strip().startswith('ignore') # or k.strip() in self.info.keys())] import_keys = [k.strip() for k in headline if not (k.strip() in self.info.keys())] si = set(import_keys) ss = set(self.schema.keys()) invalid_keys = si - ss keys = [] i = 0 duplicates = False singels = [] msg = '' while True: if len(values) != len(import_keys): msg += "%d fields in headline but %d values" % (len(import_keys),len(values)) break for k in import_keys: if k in singels: keys += (k,'%s' % k,values[i],'(duplicate)'), msg += ("duplicate %s," % k) keys[singels.index(k)] = (k,'%s' % k,values[singels.index(k)],'(duplicate)') elif k in invalid_keys and not k.startswith(IGNORE): keys += (k,NO_KEY,values[i],'(invalid)'), else: keys += (k,k,values[i],''), i += 1 singels += k, break return msg,keys ###) ###) class ApplicationImport(WAeUPImport):###( name = "application" plural_name = "%ss" % name commit_after = 1000 def create(self,mapping):###( reg_no = mapping.get('reg_no') msg = '' while True: try: self.applicants_catalog.addRecord(**mapping) except ValueError: msg = "applicant record with reg_no %s already exists" % reg_no break return reg_no,msg,mapping ###) def edit(self,mapping):###( reg_no = mapping.get('reg_no') status = mapping.get('status') msg = '' while True: res = self.applicants_catalog(reg_no = reg_no) if len(res): if res[0].status == 'created' and status != 'created': msg = "student object with id %s for %s already created, status cannot be changed" % (res[0].student_id, reg_no) elif status == 'created' and res[0].status != 'created': msg = "student object for %s has not yet been created, status cannot be set to 'created'" % (reg_no) else: self.applicants_catalog.modifyRecord(**mapping) else: msg = "applicant record with reg_no %s does not exist" % reg_no break return reg_no,msg,mapping ###) ###) class CertificateImport(WAeUPImport):###( name = "certificate" plural_name = "%ss" % name commit_after = 100000 def create(self,mapping):###( if getattr(self,'_v_certificate_list',None) is None: self._v_certificate_list = [] if getattr(self,'_v_department_certificates',None) is None: departments = self.portal_catalog(portal_type = "Department") self._v_department_certificates = {} for d in departments: certificates_folder = getattr(d.getObject(),"certificates",None) self._v_department_certificates[d.getId] = certificates_folder.objectIds() department_id = mapping['department_code'] msg = '' certificate_id = mapping.get('code') while True: department_certificates = self._v_department_certificates.get(department_id,None) if department_certificates is None: msg = "No Department with ID: %s" % department_id break if certificate_id in self._v_certificate_list: msg = "Duplicate Certificate ID: %s" % department_id break if certificate_id in department_certificates: msg = "Duplicate Certificate ID: %s" % department_id break try: d.invokeFactory('Certificate', certificate_id) except BadRequest,E: msg = "%s" % E break self._v_certificate_list.append(certificate_id) c = getattr(d,certificate_id) c.getContent().edit(mapping=mapping) break return certificate_id,msg,mapping ###) def edit(self,mapping):###( certificate_id = mapping.get('code') res = self.portal_catalog(id=certificate_id) msg = '' while True: if not res: msg = "no certificate with id: %s" % certificate_id break c = res[0].getObject() c.getContent().edit(mapping=mapping) break return certificate_id,msg,mapping ###) ###) class CourseImport(WAeUPImport):###( name = "course" plural_name = "%ss" % name commit_after = 1000 def create(self,mapping):###( if getattr(self,'_v_course_list',None) is None: self._v_course_list = [] if getattr(self,'_v_department_courses',None) is None: departments = self.portal_catalog(portal_type = "Department") self._v_department_courses = {} for department in departments: courses_folder = getattr(department.getObject(),"courses",None) if courses_folder is not None: self._v_department_courses[department.getId] = courses_folder.objectIds() department_id = mapping['department_code'] course_id = mapping.get('code','') msg = '' while True: department_courses = self._v_department_courses.get(department_id,None) if department_courses is None: msg = "no department with id: %(department_id)s" % vars() break if course_id in self._v_course_list: msg = "duplicate course id: %(course_id)s" % vars() break if course_id in department_courses: msg = "course %(course_id)s already exists in department %(department_id)s" % vars() break try: department.invokeFactory('Course', course_id) except BadRequest,E: msg = "%s" % E break self._v_course_list.append(course_id) course = getattr(department,course_id) course.getContent().edit(mapping=mapping) break return course_id,msg,mapping ###) def edit(self,mapping): ###( course_id = mapping.get('code','') course = self.courses_catalog.getRecordByKey(course_id) while True: if course is None: msg = "no course with id: %s" % course_id break course_object = getattr(getattr(self.academics_folder,course.department),course_id) course_object.getContent().edit(mapping=mapping) break return course_id,msg,mapping ###) ###) class CourseResultImport(WAeUPImport):###( """ CourseresultImport """ name = "course_result" plural_name = "%ss" % name commit_after = 1000000 required_modes = ('create','edit','remove') def getStudentRecord(self,mapping): ###( id_field_found = False msg = '' student_record = None id_count = 0 for id_key in ('matric_no','id'): id_field = mapping.get(id_key,'') if id_field: id_count += 1 search_key = id_key search_field = id_field while True: #if id_count > 1: # msg = "both id and matric_no are provided" # break if id_count == 0: msg = "neither id nor matric_no provided" break query = Eq(search_key,search_field) res = self.students_catalog.evalAdvancedQuery(query) if res: student_record = res[0] if search_key == "matric_no": mapping['id'] = student_record.id elif search_key == "id": mapping['matric_no'] = student_record.matric_no else: msg = "no student with %(search_key)s %(search_field)s" % vars() break return student_record,msg ###) def create(self,mapping):###( students_folder = self.portal_url.getPortalObject().campus.students if getattr(self,'_v_courses',None) is None: res = self.courses_catalog() self._v_courses = {} for brain in res: self._v_courses[brain.code] = brain if getattr(self,'_v_level_created',None) is None: self._v_level_created = [] msg = '' key = '' while True: course_id = mapping.get('code') if course_id not in self._v_courses.keys(): msg = "no course with id: %s" % course_id break student_record,msg = self.getStudentRecord(mapping) if msg: break student_id = student_record.id level_id = mapping.get('level_id','') code = mapping.get('code','') if student_id not in self._v_level_created: try: context = getattr(getattr(students_folder, "%(student_id)s" % vars()), 'study_course') except: msg = "could not create level %(level_id)s for %(student_id)s" % vars() break if level_id not in context.objectIds(): context.invokeFactory('StudentStudyLevel',"%(level_id)s" % vars()) level = getattr(context,"%(level_id)s" % vars()) self.portal_workflow.doActionFor(level,'open') # the session string must not be copied into the level object current_verdict = getattr(student_record,'current_verdict','') current_session = getattr(student_record,'current_session','') if current_verdict and student_record.current_level == level_id: level.getContent().edit(mapping={'verdict': "%s" % current_verdict, 'session': "%s" % current_session, }) self.portal_workflow.doActionFor(level,'close') self._v_level_created += student_id, mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % vars() for k in ('semester','credits',): mapping[k] = getattr(self._v_courses[course_id],k) try: self.course_results.addRecord(**mapping) except ValueError: msg = "course result already exists: %s" % key break return key,msg,mapping ###) def edit(self,mapping): ###( msg = '' key = '' while True: student_record,msg = self.getStudentRecord(mapping) if msg: break student_id = student_record.id level_id = mapping.get('level_id','') code = mapping.get('code','') code = mapping['code'] mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % vars() if self.course_results.getRecordByKey(key) is None: msg = "no course result with key %(key)s" % vars() break self.course_results.modifyRecord(**mapping) break return key,msg,mapping ###) def remove(self,mapping):###( key = '' msg = '' while True: student_record,msg = self.getStudentRecord(mapping) if msg: break student_id = student_record.id level_id = mapping.get('level_id','') code = mapping.get('code','') key = "%(student_id)s|%(level_id)s|%(code)s" % vars() if self.course_results.getRecordByKey(key) is None: msg = "no course result with key %(key)s" % vars() break self.course_results.deleteRecord(key) break return key,msg,mapping ###) ###) class CertificateCourseImport(WAeUPImport):###( name = "certificate_course" plural_name = "%ss" % name commit_after = 100000 required_modes = ('create','edit') def create(self,mapping): if getattr(self,'_v_courses',None) is None: res = self.courses_catalog() self._v_courses= [course.code for course in res] if getattr(self,'_v_ceritficates',None) is None: res = self.portal_catalog(portal_type = "Certificate") self._v_certificates = {} for cert in res: self._v_certificates[cert.getId] = cert.getObject() msg = '' while True: certificate_course_id = mapping.get('code') if certificate_course_id not in self._v_courses: msg = "no course with id: %s" % certificate_course_id break cert_id = mapping['certificate_code'] cert = self._v_certificates.get(cert_id,None) if cert is None: msg = "no certificate with id: %s" % cert_id break level_id = mapping.get('level') level = getattr(cert,level_id,None) if level is None: cert.invokeFactory('StudyLevel', level_id) level = getattr(cert,level_id,None) elif hasattr(level,certificate_course_id): msg = "duplicate certificate course id: %(certificate_course_id)s " % vars() msg += "in %(cert_id)s/ %(level_id)s" % vars() break level.invokeFactory('CertificateCourse', certificate_course_id) c = getattr(level,certificate_course_id) c.getContent().edit(mapping=mapping) break return certificate_course_id,msg,mapping ###) class DepartmentImport(WAeUPImport):###( name = "department" plural_name = "%ss" % name commit_after = 1000 def create(self,mapping):###( "create a department in the correct faculty" faculty_id = mapping['faculty_code'] msg = '' if getattr(self,'_v_faculties',None) is None: res = self.portal_catalog(portal_type = "Department") self._v_faculties = {} for f in res: self._v_faculties[f.getId] = f.getObject() department_id = mapping.get('code','') while True: faculty = self._v_faculties.get(faculty_id,None) if faculty is None: msg = "no faculty with id: %s" % faculty_id break else: d = getattr(faculty,department_id,None) if d is None or d.portal_type == "Faculty": try: faculty.invokeFactory('Department', department_id) except BadRequest,E: msg = "%s" % E break d = getattr(faculty,department_id) d.invokeFactory('CoursesFolder','courses') courses = getattr(d,'courses') dict = {'Title': 'Courses'} courses.getContent().edit(mapping=dict) d.invokeFactory('CertificatesFolder','certificates') certificates = getattr(d,'certificates') dict = {'Title': 'Certificates'} certificates.getContent().edit(mapping=dict) d.getContent().edit(mapping=mapping) break return department_id,msg,mapping ###) def edit(self,mapping): ###( "edit a department in the correct faculty" academics_folder = self.portal_url.getPortalObject().campus.academics faculty_id = mapping['faculty_code'] department_id = mapping.get('code','') msg = '' while True: try: d = getattr(getattr(academics_folder,faculty_id),department_id,None) except KeyError: msg = "department %s or faculty %s wrong" % (department_id,faculty_id) break if d is None or d.portal_type == "Faculty": msg = "department %s not found" % (department_id) break d.getContent().edit(mapping=mapping) break return department_id,msg,mapping ###) ###) class FacultyImport(WAeUPImport):###( name = "faculty" plural_name = "faculties" commit_after = 100 def create(self,mapping): ###( "create a faculty" academics_folder = self.portal_url.getPortalObject().campus.academics faculty_id = mapping.get('code','') msg = '' while True: if faculty_id in academics_folder.objectIds(): msg = "faculty with id: %s exists" % faculty_id break logger.info('Creating Faculty %(code)s, %(title)s' % mapping) try: academics_folder.invokeFactory('Faculty', faculty_id) except BadRequest,E: msg = "%s" % E break f = getattr(academics_folder,faculty_id,None) f.getContent().edit(mapping=mapping) break return faculty_id,msg,mapping ###) def edit(self,mapping): ###( "edit a faculty" academics_folder = self.portal_url.getPortalObject().campus.academics faculty_id = mapping['code'] msg = '' while True: f = getattr(academics_folder,faculty_id,None) if f is None: msg = "faculty with id: %s does not exist" % faculty_id f.getContent().edit(mapping=mapping) break return faculty_id,msg,mapping ###) ###) class StudentImport(WAeUPImport):###( name = "student" plural_name = "%ss" % name commit_after = 100 field2types_student = { ###( 'StudentApplication': {'id': 'application', 'title': 'Application Data', 'wf_transition_return': 'close', 'wf_transition_admit': 'remain', 'fields': ('jamb_reg_no', 'entry_mode', 'entry_session', 'jamb_score', 'app_email', 'jamb_age', 'jamb_state', 'jamb_lga', 'jamb_sex', ) }, #'StudentPume': # {'id': 'pume', # 'title': 'Pume Data', # 'wf_transition_return': 'close', # 'wf_transition_admit': 'close', # 'fields': # ('pume_score', # ) # }, 'StudentClearance': {'id': 'clearance', 'title': 'Clearance/Eligibility Record', 'wf_transition_return': 'close', 'wf_transition_admit': 'remain', 'fields': ('matric_no', 'nationality', 'lga', 'birthday', ) }, 'StudentPersonal': {'id': 'personal', 'title': 'Personal Data', 'wf_transition_return': 'open', 'wf_transition_admit': 'remain', 'fields': ('firstname', 'middlename', 'lastname', 'sex', 'email', 'phone', 'perm_address', ) }, 'StudentStudyCourse': {'id': 'study_course', 'title': 'Study Course', 'wf_transition_return': 'open', 'wf_transition_admit': 'remain', 'fields': ('study_course', 'current_level', 'current_session', 'current_mode', 'current_verdict', 'previous_verdict', ) }, # 'StudentStudyLevel': # {'id': 'current_level', # 'title': '', # 'wf_transition_return': 'open', # 'wf_transition_admit': 'remain', # 'fields': # ('verdict', # 'session', # ) # }, 'PaymentsFolder': {'id': 'payments', 'title': 'Payments', 'wf_transition_return': 'open', 'wf_transition_admit': 'open', 'fields': () }, } ###) def create(self,mapping): ###( "create student records due import" logger = logging.getLogger('WAeUPTool.mass_create_student') students_folder = self.portal_url.getPortalObject().campus.students jamb_reg_no = mapping.get('jamb_reg_no',None) matric_no = mapping.get('matric_no',None) msg = '' student_id = mapping.get('id',None) while True: if student_id: msg = "student_id must not be specified in create mode" break if jamb_reg_no: res = self.students_catalog(jamb_reg_no = jamb_reg_no) if res: msg = "jamb_reg_no exists" break if matric_no: res = self.students_catalog(matric_no = matric_no) if res: msg = "matric_no exists" break if not matric_no and not jamb_reg_no: msg = "jamb_reg_no or matric_no must be specified" break student_id = self.waeup_tool.generateStudentId('?') students_folder.invokeFactory('Student', student_id) student_obj = getattr(students_folder,student_id) f2t = self.field2types_student d = {} transition = mapping.get('reg_transition','admit') if transition not in ('admit','return'): msg = "no valid transition provided" break for pt in f2t.keys(): student_obj.invokeFactory(pt,f2t[pt]['id']) sub_obj = getattr(student_obj,f2t[pt]['id']) sub_doc = sub_obj.getContent() d['Title'] = f2t[pt]['title'] for field in f2t[pt]['fields']: d[field] = mapping.get(field,'') if pt == "StudentApplication": #d['jamb_sex'] = 'M' #if mapping.get('sex'): # d['jamb_sex'] = 'F' d['jamb_firstname'] = mapping.get('firstname',None) d['jamb_middlename'] = mapping.get('middlename',None) d['jamb_lastname'] = mapping.get('lastname',None) # if pt == "StudyCourse": # for von,zu in (('entry_mode','current_mode'), # ('entry_session','current_session')): # if mapping.get(zu,None) is None and mapping.get(von,None) is not None: # d[zu] = mapping[von] sub_doc.edit(mapping = d) #import pdb;pdb.set_trace() new_state = f2t[pt]['wf_transition_%(transition)s' % vars()] if new_state != "remain": self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj) self.portal_workflow.doActionFor(student_obj,transition) student_obj.manage_setLocalRoles(student_id, ['Owner',]) mapping['id'] = student_id break return student_id,msg,mapping ###) def edit(self,mapping): ###( wftool = self.portal_workflow "edit student records due import" logger = logging.getLogger('WAeUPTool.mass_edit_student') students_folder = self.portal_url.getPortalObject().campus.students student_id = mapping.get('id',None) jamb_reg_no = mapping.get('jamb_reg_no',None) matric_no = mapping.get('matric_no',None) editable_keys = mapping.keys() msg = '' while True: if student_id: res = self.students_catalog(id = student_id) if not res: msg = "no student with id %s" % student_id break student_record = res[0] if matric_no and student_record.matric_no: if matric_no != student_record.matric_no: msg = "old matric_no %s overwritten with %s" % (student_record.matric_no,matric_no) #logger.info("%s, old matric_no %s overwritten with %s" % (student_record.id,student_record.matric_no,matric_no)) if jamb_reg_no and student_record.jamb_reg_no: if jamb_reg_no != student_record.jamb_reg_no: msg = "old reg_no %s overwritten with %s" % (student_record.jamb_reg_no,jamb_reg_no) #logger.info("%s, old reg_no %s overwritten with %s" % (student_record.id,student_record.jamb_reg_no,jamb_reg_no)) elif jamb_reg_no: res = self.students_catalog(jamb_reg_no = jamb_reg_no) if not res: msg = "no student with jamb_reg_no %s" % jamb_reg_no break student_record = res[0] editable_keys.remove('jamb_reg_no') elif matric_no: res = self.students_catalog(matric_no = matric_no) if not res: msg = "no student with matric_no %s" % matric_no break student_record = res[0] editable_keys.remove('matric_no') ## included only to change wf state from admitted to returning #if student_record.review_state not in ('admitted','objection_raised'): # return '%s' % student_record.id ,"student is not in state admitted or objection_raised" ## end inclusion student_id = student_record.id student_obj = getattr(students_folder,student_id) f2t = self.field2types_student d = {} any_change = False #special treatment for StudentStudyLevel d['verdict'] = mapping.get('current_verdict','') d['session'] = mapping.get('current_session','') current_level = mapping.get('current_level','') while d['session'] and d['verdict'] and current_level: sub_obj = getattr(student_obj,'study_course',None) if sub_obj is None: break level_obj = getattr(sub_obj,current_level,None) if level_obj is None: break any_change = True level_obj.getContent().edit(mapping = d) try: wftool.doActionFor(level_obj,'close') except: pass break for pt in f2t.keys(): #if pt == "StudentApplication": # d['jamb_sex'] = 'M' # if mapping.get('sex'): # d['jamb_sex'] = 'F' intersect = set(f2t[pt]['fields']).intersection(set(editable_keys)) if intersect and pt not in ('StudentStudyLevel',): object_id = f2t[pt]['id'] sub_obj = getattr(student_obj,object_id,None) if sub_obj is None: try: student_obj.invokeFactory(pt,object_id) except: continue sub_obj = getattr(student_obj,object_id) if f2t[pt]['title'] != '': d['Title'] = f2t[pt]['title'] sub_doc = sub_obj.getContent() for field in intersect: changed = False if getattr(sub_doc,field,None) != mapping.get(field,''): any_change = True changed = True d[field] = mapping.get(field,'') if changed: sub_doc.edit(mapping = d) ## included only to change wf state from admitted to returning # if student_record.review_state in ('admitted','objection_raised'): # new_state = f2t[pt]['wf_transition_return'] # sub_obj = getattr(student_obj,f2t[pt]['id'],None) # if sub_obj and new_state != "remain": # try: # self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj) # except: # #logger.info('%s, wf transition %s of %s failed' % (student_id,new_state,sub_obj.id)) # pass #if student_record.review_state in ('admitted','objection_raised'): # wfaction = 'return' # try: # self.portal_workflow.doActionFor(student_obj,wfaction) # logger.info('%s, wf state changed' % student_id) # any_change = True # except: # logger.info('%s, wf transition failed, old state = %s' % (student_id,student_record.review_state)) # pass ## end inclusion break # if not any_change: # msg = 'not modified' return student_id,msg,mapping ###) ###) class VerdictImport(WAeUPImport):###( """ VerdictImport """ name = "verdict" plural_name = "%ss" % name commit_after = 100000 required_modes = ('create','edit') def create(self,mapping): "edit student verdicts and create StudentStudyLevel object if not existent" wftool = self.portal_workflow logger = logging.getLogger('WAeUPTool.mass_edit_verdict') students_folder = self.portal_url.getPortalObject().campus.students student_id = mapping.get('id',None) matric_no = mapping.get('matric_no',None) editable_keys = mapping.keys() while True: key = '' msg = '' if student_id: student_record = self.students_catalog.getRecordByKey(student_id) if student_record is None: #return '',"no student with id %s" % student_id msg = "no student with id %s" % student_id break if matric_no and student_record.matric_no and matric_no != student_record.matric_no: msg = 'student %s: matric_no %s does not match %s' % (student_record.id, student_record.matric_no, matric_no) break mapping['matric_no'] = student_record.matric_no elif matric_no: res = self.students_catalog(matric_no = matric_no) if not res: msg = "no student with matric_no %s" % matric_no break student_record = res[0] editable_keys.remove('matric_no') else: msg = "no id or matric_no specified" break student_id = student_record.id mapping['id'] = student_id d = {} #import pdb;pdb.set_trace() any_change = False #special treatment for StudentStudyLevel current_session = d['session'] = mapping.get('current_session','') if current_session and student_record.session != current_session: msg = 'student %s: imported session %s does not match current_session %s' % (student_id, current_session, student_record.session) break current_level = mapping.get('current_level','') if not current_level.isdigit(): msg = 'student %s: imported level is empty' % (student_id,) break if current_level and student_record.level != current_level: msg = 'student %s: imported level %s does not match current_level %s' % (student_id, current_level, student_record.level) break student_review_state = student_record.review_state if student_review_state == 'deactivated': msg = "student %s in review_state %s" % (student_id, student_review_state) break if student_review_state not in ('courses_validated','returning'): msg = "student %s in wrong review_state %s" % (student_id, student_review_state) break student_obj = getattr(students_folder,student_id) # f2t = self.field2types_student study_course_obj = getattr(student_obj,'study_course',None) if study_course_obj is None: msg = 'student %s: no study_course object' % student_id break level_obj = getattr(study_course_obj,current_level,None) if level_obj is None: # The only difference to the edit method is that we create a StudentStudyLevel object try: study_course_obj.invokeFactory('StudentStudyLevel',"%s" % current_level) level_obj = getattr(context,"%s" % current_level) level_obj.portal_workflow.doActionFor(level,'open') except: continue #msg = 'student %s: no study_level object for level %s' % (student_id, # current_level) #break verdict = d['verdict'] = d['current_verdict'] = mapping.get('current_verdict','') #if verdict == student_record.verdict: # msg = 'student %s: verdict already set to %s' % (student_id, # verdict) level_review_state = wftool.getInfoFor(level_obj,'review_state',None) if level_review_state != "closed": wftool.doActionFor(level_obj,'close') # msg = 'student %s: level %s is not closed' % (student_id, # current_level) study_course_obj.getContent().edit(mapping = d) level_obj.getContent().edit(mapping = d) if student_review_state != "returning": wftool.doActionFor(student_obj,'return') # try: # wftool.doActionFor(level_obj,'close') # except: # pass break return student_id,msg,mapping def edit(self,mapping): "edit student verdicts" wftool = self.portal_workflow logger = logging.getLogger('WAeUPTool.mass_edit_verdict') students_folder = self.portal_url.getPortalObject().campus.students student_id = mapping.get('id',None) matric_no = mapping.get('matric_no',None) editable_keys = mapping.keys() while True: key = '' msg = '' if student_id: student_record = self.students_catalog.getRecordByKey(student_id) if student_record is None: #return '',"no student with id %s" % student_id msg = "no student with id %s" % student_id break if matric_no and student_record.matric_no and matric_no != student_record.matric_no: msg = 'student %s: matric_no %s does not match %s' % (student_record.id, student_record.matric_no, matric_no) break mapping['matric_no'] = student_record.matric_no elif matric_no: res = self.students_catalog(matric_no = matric_no) if not res: msg = "no student with matric_no %s" % matric_no break student_record = res[0] editable_keys.remove('matric_no') else: msg = "no id or matric_no specified" break student_id = student_record.id mapping['id'] = student_id d = {} #import pdb;pdb.set_trace() any_change = False #special treatment for StudentStudyLevel current_session = d['session'] = mapping.get('current_session','') if current_session and student_record.session != current_session: msg = 'student %s: imported session %s does not match current_session %s' % (student_id, current_session, student_record.session) break current_level = mapping.get('current_level','') if not current_level.isdigit(): msg = 'student %s: imported level is empty' % (student_id,) break if current_level and student_record.level != current_level: msg = 'student %s: imported level %s does not match current_level %s' % (student_id, current_level, student_record.level) break student_review_state = student_record.review_state if student_review_state == 'deactivated': msg = "student %s in review_state %s" % (student_id, student_review_state) break if student_review_state not in ('courses_validated','returning'): msg = "student %s in wrong review_state %s" % (student_id, student_review_state) break student_obj = getattr(students_folder,student_id) # f2t = self.field2types_student study_course_obj = getattr(student_obj,'study_course',None) if study_course_obj is None: msg = 'student %s: no study_course object' % student_id break level_obj = getattr(study_course_obj,current_level,None) if level_obj is None: msg = 'student %s: no study_level object for level %s' % (student_id, current_level) break verdict = d['verdict'] = d['current_verdict'] = mapping.get('current_verdict','') #if verdict == student_record.verdict: # msg = 'student %s: verdict already set to %s' % (student_id, # verdict) level_review_state = wftool.getInfoFor(level_obj,'review_state',None) if level_review_state != "closed": wftool.doActionFor(level_obj,'close') # msg = 'student %s: level %s is not closed' % (student_id, # current_level) study_course_obj.getContent().edit(mapping = d) level_obj.getContent().edit(mapping = d) if student_review_state != "returning": wftool.doActionFor(student_obj,'return') # try: # wftool.doActionFor(level_obj,'close') # except: # pass break return student_id,msg,mapping ###)