source: WAeUP_SRP/trunk/WAeUPImport.py @ 5193

Last change on this file since 5193 was 5192, checked in by Henrik Bettermann, 14 years ago

enable reg_transition reject_clearance

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