source: WAeUP_SRP/trunk/WAeUPImport.py @ 3994

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

export field names must be unique but, unfortunately, firstname, middlename and lastname are not, thus we have to omit them

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