source: WAeUP_SRP/trunk/WAeUPImport.py @ 4298

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

fix traceback #2

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