source: WAeUP_SRP/trunk/WAeUPImport.py @ 5215

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

do not change the record if session_ids do not match

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