source: WAeUP_SRP/trunk/WAeUPImport.py @ 3841

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