source: WAeUP_SRP/trunk/WAeUPImport.py @ 4403

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

store ids when removing students and check for removed ids when csdding new students

WAeUPTable alraedy contains methods for position ind course calculation

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