source: WAeUP_SRP/trunk/WAeUPImport.py @ 5022

Last change on this file since 5022 was 5020, checked in by Henrik Bettermann, 15 years ago

do not remove payment records, because an uncatalog error occurs, if payment objects exist

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