source: WAeUP_SRP/trunk/WAeUPImport.py @ 5208

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

Notreparatur

  • Property svn:keywords set to Id
File size: 68.7 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 5206 2010-05-26 04:27:02Z 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            # don't overwrite session id but check if session ids match
531            # (helps to avoid overwriting of course results)
532            session_in_course_result = self.course_results.getRecordByKey(key)['session_id']
533            if mapping.get('session_id','') and not session_in_course_result == mapping.get('session_id',''):
534                msg =  "import session_id %s does not match session_id %s in course result" % (mapping['session_id'],session_in_course_result)
535            self.course_results.modifyRecord(**mapping)
536            break
537        return key,msg,mapping
538    ###)
539
540    def remove(self,mapping):###(
541        key = ''
542        msg = ''
543        matric_no = mapping.get('matric_no','')
544        id = mapping.get('id','')
545        while True:
546            result = self.findStudent('edit',student_id=id,matric_no=matric_no)
547            msg = result['msg']
548            if msg:
549                break
550            student_record = result['student_record']
551            student_id = student_record.id
552            level_id = mapping.get('level_id','')
553            code = mapping.get('code','')
554            key = "%(student_id)s|%(level_id)s|%(code)s" % vars()
555            if self.course_results.getRecordByKey(key) is None:
556                msg =  "no course result with key %(key)s" % vars()
557                break
558            self.course_results.deleteRecord(key)
559            break
560        return key,msg,mapping
561    ###)
562###)
563
564class CertificateCourseImport(WAeUPImport):###(
565    name = "certificate_course"
566    plural_name = "%ss" % name
567    commit_after = 1000
568    required_modes = ('create','edit')
569
570    def create(self,mapping):
571        if getattr(self,'_v_courses',None) is None:
572            res = self.courses_catalog()
573            self._v_courses= [course.code for course in res]
574        if getattr(self,'_v_ceritficates',None) is None:
575            res = self.portal_catalog(portal_type = "Certificate")
576            self._v_certificates = {}
577            for cert in res:
578                self._v_certificates[cert.getId] = cert.getObject()
579        msg = ''
580        while True:
581            certificate_course_id = mapping.get('code')
582            if certificate_course_id not in self._v_courses:
583                msg =  "no course with id: %s" % certificate_course_id
584                break
585            cert_id = mapping['certificate_code']
586            cert = self._v_certificates.get(cert_id,None)
587            if cert is None:
588                msg =  "no certificate with id: %s" % cert_id
589                break
590            level_id = mapping.get('level')
591            level = getattr(cert,level_id,None)
592            if level is None:
593                cert.invokeFactory('StudyLevel', level_id)
594                level = getattr(cert,level_id,None)
595            elif hasattr(level,certificate_course_id):
596                msg =  "duplicate certificate course id: %(certificate_course_id)s " % vars()
597                msg += "in %(cert_id)s/ %(level_id)s" % vars()
598                break
599            level.invokeFactory('CertificateCourse', certificate_course_id)
600            c = getattr(level,certificate_course_id)
601            c.getContent().edit(mapping=mapping)
602            break
603        return certificate_course_id,msg,mapping
604    ###)
605
606class DepartmentImport(WAeUPImport):###(
607    name = "department"
608    plural_name = "%ss" % name
609    commit_after = 1000
610
611    def create(self,mapping):###(
612        "create a department in the correct faculty"
613        faculty_id = mapping['faculty_code']
614        msg = ''
615        if getattr(self,'_v_faculties',None) is None:
616            res = self.portal_catalog(portal_type = "Faculty")
617            self._v_faculties = {}
618            for f in res:
619                self._v_faculties[f.getId] = f.getObject()
620        department_id = mapping.get('code','')
621        while True:
622            faculty = self._v_faculties.get(faculty_id,None)
623            if faculty is None:
624                msg =  "no faculty with id: %s" % faculty_id
625                break
626            else:
627                d = getattr(faculty,department_id,None)
628                if d is None or d.portal_type == "Faculty":
629                    try:
630                        faculty.invokeFactory('Department', department_id)
631                    except BadRequest,E:
632                        msg =  "%s" % E
633                        break
634                    d = getattr(faculty,department_id)
635                    d.invokeFactory('CoursesFolder','courses')
636                    courses = getattr(d,'courses')
637                    dict = {'Title': 'Courses'}
638                    courses.getContent().edit(mapping=dict)
639                    d.invokeFactory('CertificatesFolder','certificates')
640                    certificates = getattr(d,'certificates')
641                    dict = {'Title': 'Certificates'}
642                    certificates.getContent().edit(mapping=dict)
643                    d.getContent().edit(mapping=mapping)
644            break
645        return department_id,msg,mapping
646    ###)
647
648    def edit(self,mapping): ###(
649        "edit a department in the correct faculty"
650        academics_folder = self.portal_url.getPortalObject().campus.academics
651        faculty_id = mapping['faculty_code']
652        department_id = mapping.get('code','')
653        msg = ''
654        while True:
655            try:
656                d = getattr(getattr(academics_folder,faculty_id),department_id,None)
657            except KeyError:
658                msg =  "department %s or faculty %s wrong" % (department_id,faculty_id)
659                break
660            if d is None or d.portal_type == "Faculty":
661                msg =  "department %s not found" % (department_id)
662                break
663            d.getContent().edit(mapping=mapping)
664            break
665        return department_id,msg,mapping
666    ###)
667###)
668
669class FacultyImport(WAeUPImport):###(
670    name = "faculty"
671    plural_name = "faculties"
672    commit_after = 100
673   
674
675    def create(self,mapping): ###(
676        "create a faculty"
677        academics_folder = self.portal_url.getPortalObject().campus.academics
678        faculty_id = mapping.get('code','')
679        msg = ''
680        while True:
681            if faculty_id in academics_folder.objectIds():
682                msg =  "faculty with id: %s exists" % faculty_id
683                break
684            try:
685                academics_folder.invokeFactory('Faculty', faculty_id)
686            except BadRequest,E:
687                msg =  "%s" % E
688                break
689            f = getattr(academics_folder,faculty_id,None)
690            f.getContent().edit(mapping=mapping)
691            break
692        return faculty_id,msg,mapping
693        ###)
694
695    def edit(self,mapping): ###(
696        "edit a faculty"
697        academics_folder = self.portal_url.getPortalObject().campus.academics
698        faculty_id = mapping['code']
699        msg = ''
700        while True:
701            f = getattr(academics_folder,faculty_id,None)
702            if f is None:
703                msg =  "faculty with id: %s does not exist" % faculty_id
704            f.getContent().edit(mapping=mapping)
705            break
706        return faculty_id,msg,mapping
707    ###)
708###)
709
710class StudentImport(WAeUPImport):###(
711    name = "student"
712    plural_name = "%ss" % name
713    commit_after = 100
714
715    field2types_student = {   ###(
716                      'StudentApplication':
717                          {'id': 'application',
718                           #'title': 'Application Data',
719                           'wf_transition_return': 'close',
720                           'wf_transition_admit': 'remain',
721                           'wf_transition_graduate': 'close',
722                           'wf_transition_pay_school_fee': 'close',
723                           'wf_transition_validate_courses': 'close',
724                           'wf_transition_reject_clearance': 'remain',
725                           'fields':
726                             ('jamb_reg_no',
727                              'entry_mode',
728                              'entry_session',
729                              'jamb_score',
730                              'app_email',
731                              'app_mobile',
732                              'jamb_age',
733                              'jamb_state',
734                              'jamb_lga',
735                              'jamb_sex',
736                              'app_ac_pin',
737                              'app_reg_pin',
738                              'app_ac_date',                             
739                              )
740                              },
741                      'StudentClearance':
742                          {'id': 'clearance',
743                           #'title': 'Clearance/Eligibility Record',
744                           'wf_transition_return': 'close',
745                           'wf_transition_admit': 'remain',
746                           'wf_transition_graduate': 'close',
747                           'wf_transition_pay_school_fee': 'close',
748                           'wf_transition_validate_courses': 'close',
749                           'wf_transition_reject_clearance': 'open',
750                           'fields':
751                              ('matric_no',
752                              'nationality',
753                              'lga',
754                              'birthday',
755                              'clr_ac_pin',
756                              'request_date',
757                              'cleared_date',
758                              'clearance_officer',
759                              )
760                              },
761                         'StudentPersonal':
762                          {'id': 'personal',
763                           #'title': 'Personal Data',
764                           'wf_transition_return': 'open',
765                           'wf_transition_admit': 'remain',
766                           'wf_transition_graduate': 'close',
767                           'wf_transition_pay_school_fee': 'open',
768                           'wf_transition_validate_courses': 'open',
769                           'wf_transition_reject_clearance': 'remain',
770                           'fields':
771                             ('firstname',
772                              'middlename',
773                              'lastname',
774                              'sex',
775                              'email',
776                              'phone',
777                              'perm_address',
778                              'marit_stat',
779                              'disabled',
780                              )
781                              },
782                         'StudentStudyCourse':
783                          {'id': 'study_course',
784                           #'title': 'Study Course',
785                           'wf_transition_return': 'open',
786                           'wf_transition_admit': 'remain',
787                           'wf_transition_graduate': 'close',
788                           'wf_transition_pay_school_fee': 'open',
789                           'wf_transition_validate_courses': 'open',
790                           'wf_transition_reject_clearance': 'remain',
791                           'fields':
792                             ('study_course',
793                              'current_level',
794                              'current_session',
795                              'current_mode',  #is no longer used and visible but can still be imported
796                              'current_verdict',
797                              'previous_verdict',
798                              )
799                              },
800                         'StudentAccommodation':
801                          {'id': 'accommodation_final',
802                           'title': '',
803                           'wf_transition_return': 'remain',
804                           'wf_transition_admit': 'remain',
805                           'wf_transition_graduate': 'remain',
806                           'wf_transition_pay_school_fee': 'remain',
807                           'wf_transition_validate_courses': 'remain',
808                           'wf_transition_reject_clearance': 'remain',
809                           'fields':
810                           ('acco_maint_date',
811                              'acco_maint_code',
812                              'acco_maint_fee',
813                              'acco_maint_sc_pin',
814                              'acco_maint_pay_id',
815                              'acco_res_date',
816                              'acco_res_sc_pin',
817                              'bed',
818                              'session',
819                              'student_status',
820                              )     
821                              },
822                         'PaymentsFolder':
823                          {'id': 'payments',
824                           #'title': 'Payments',
825                           'wf_transition_return': 'open',
826                           'wf_transition_admit': 'open',
827                           'wf_transition_graduate': 'close',
828                           'wf_transition_pay_school_fee': 'open',
829                           'wf_transition_validate_courses': 'open',
830                           'wf_transition_reject_clearance': 'remain',
831                           'fields':
832                             ()
833                              },
834                         }
835    ###)
836
837    def create(self,mapping): ###(
838        "create student records due import"
839        logger = logging.getLogger('WAeUPImport.StudentImport.create')
840        students_folder = self.portal_url.getPortalObject().campus.students
841        jamb_reg_no = mapping.get('jamb_reg_no',None)
842        matric_no = mapping.get('matric_no',None)
843        entry_mode = mapping.get('entry_mode',None)
844        password = mapping.get('password',None)
845        msg = ''
846        student_id = mapping.get('id',None)
847        while True:
848            if student_id:
849                #msg = "student_id must not be specified in create mode"
850                #break
851                res = self.students_catalog(id = student_id)
852                if res:
853                    msg = "student_id %s already assigned" % res[0].id
854                    break     
855                self.waeup_tool.restorePictureFolder(student_id)           
856            else:
857                student_id = self.waeup_tool.generateStudentId('?')
858            if jamb_reg_no and not entry_mode == 'transfer':
859                res = self.students_catalog(jamb_reg_no = jamb_reg_no)
860                if res:
861                    msg = "jamb_reg_no already assigned to student %s" % res[0].id
862                    break
863            if matric_no:
864                res = self.students_catalog(matric_no = matric_no)
865                if res:
866                    msg = "matric_no already assigned to student %s" % res[0].id
867                    break
868            if not matric_no and not jamb_reg_no:
869                msg = "jamb_reg_no or matric_no must be specified"
870                break
871           
872            students_folder.invokeFactory('Student', student_id)
873            student_obj = getattr(students_folder,student_id)
874            f2t = self.field2types_student
875            d = {}
876            transition = mapping.get('reg_transition','admit')
877            if transition not in ('admit','return','pay_school_fee','validate_courses','graduate','reject_clearance'):
878                msg = "no valid transition provided"
879                break
880            for pt in f2t.keys():
881                if pt == 'StudentAccommodation':
882                    if mapping.get('bed',None):
883                        student_obj.invokeFactory(pt,f2t[pt]['id'])
884                    else:
885                        continue
886                else:
887                    student_obj.invokeFactory(pt,f2t[pt]['id'])
888                sub_obj = getattr(student_obj,f2t[pt]['id'])
889                sub_doc = sub_obj.getContent()
890                #d['Title'] = f2t[pt]['title']
891                for field in f2t[pt]['fields']:
892                    d[field] = mapping.get(field,'')
893
894                if pt == "StudentApplication":
895                    #d['jamb_sex']  = 'M'
896                    #if mapping.get('sex'):
897                    #    d['jamb_sex']  = 'F'
898                    d['jamb_firstname'] = mapping.get('firstname',None)
899                    d['jamb_middlename'] = mapping.get('middlename',None)
900                    d['jamb_lastname'] = mapping.get('lastname',None)
901
902                # if pt == "StudyCourse":
903                #     for von,zu in (('entry_mode','current_mode'),
904                #                    ('entry_session','current_session')):
905                #         if mapping.get(zu,None) is None and mapping.get(von,None) is not None:
906                #             d[zu] = mapping[von]
907                sub_doc.edit(mapping = d)
908
909                #import pdb;pdb.set_trace()
910                new_state = f2t[pt]['wf_transition_%(transition)s' % vars()]
911                if new_state != "remain":
912                    self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
913            self.portal_workflow.doActionFor(student_obj,transition)
914            student_obj.manage_setLocalRoles(student_id, ['Owner',])
915            mapping['id'] = student_id
916            if password:
917                self.waeup_tool.makeStudentMember(student_id,password)
918            break
919        return student_id,msg,mapping
920    ###)
921
922    def remove(self,mapping): ###(
923        "remove student records due import"
924        logger = logging.getLogger('WAeUPImport.StudentImport.remove')
925        students_folder = self.portal_url.getPortalObject().campus.students
926        stdir = self.portal_directories.students
927        student_id = mapping.get('id',None)
928        msg = ''
929        export_file = "%s/export/students_removed.csv" % (i_home)
930        reimport_file = "%s/export/students_for_reimport.csv" % (i_home)
931       
932        toexport_for_reimport = {
933       
934                    'application':
935                             ('jamb_reg_no',
936                              'entry_mode',
937                              'entry_session',
938                              'jamb_score',
939                              'app_email',
940                              'app_mobile',
941                              'jamb_age',
942                              'jamb_state',
943                              'jamb_lga',
944                              'jamb_sex',
945                              'app_ac_pin',
946                              'app_reg_pin',
947                              'app_ac_date',                             
948                              ),
949                    'clearance':
950                              ('matric_no',
951                              'nationality',
952                              'lga',
953                              'birthday',
954                              'clr_ac_pin',
955                              'request_date',
956                              'cleared_date',
957                              'clearance_officer',
958                              ),
959                    'study_course':
960                              ('study_course',
961                              'current_level',
962                              'current_session',
963                              'current_verdict',
964                              'previous_verdict',
965                              ),
966                    'personal': 
967                             ('firstname',
968                              'middlename',
969                              'lastname',
970                              'sex',
971                              'email',
972                              'phone',
973                              'perm_address',
974                              'marit_stat',
975                              'disabled',
976                              ),
977                    'accommodation': 
978                             ('acco_maint_date',
979                              'acco_maint_code',
980                              'acco_maint_fee',
981                              'acco_maint_sc_pin',
982                              'acco_maint_pay_id',
983                              'acco_res_date',
984                              'acco_res_sc_pin',
985                              'bed',
986                              'session',
987                              'student_status',
988                              ),                             
989                   }
990
991        sub_types = ['StudentApplication','StudentClearance','StudentPersonal','StudentStudyCourse','StudentAccommodation']
992        non_image_keys = {}
993        for i in sub_types:
994            pt_ob = getattr(self.types_tool,i)
995            sub_schemas = pt_ob.schemas
996            for i in sub_schemas:
997                if i.startswith('student_'):
998                    schema = getattr(self.schema_tool,i)
999                    field_id = i.replace('student_','')
1000                    non_image_keys[field_id] = [key for key in schema.keys()
1001                                                if schema[key].meta_type != "CPS Image Field"]
1002       
1003        # export field names must be unique but, unfortunately, firstname, middlename and lastname are not
1004        # thus we have to omit them
1005        non_image_keys['clearance'].remove('firstname')
1006        non_image_keys['clearance'].remove('middlename')
1007        non_image_keys['clearance'].remove('lastname')
1008        toexport = non_image_keys
1009        #import pdb;pdb.set_trace()
1010        while True:
1011            if hasattr(students_folder,student_id):
1012                # begin export
1013                line = []
1014                fields = ['student_id','reg_state','password']
1015                line_for_reimport = []
1016                fields_for_reimport = ['student_id','reg_state','password','import_mode']               
1017                #fields = []
1018                #for f in self.students_catalog.schema():
1019                #    fields.append(f)               
1020                for k in toexport.keys():
1021                    for f in toexport[k]:
1022                        fields.append(f)
1023                for k in toexport_for_reimport.keys():
1024                    for f in toexport_for_reimport[k]:
1025                        fields_for_reimport.append(f)                       
1026                if not os.path.exists(export_file):       
1027                    headline = ','.join(fields)
1028                    open(export_file,"a").write(headline +'\n')
1029                if not os.path.exists(reimport_file): 
1030                    headline_for_reimport = ','.join(fields_for_reimport)                   
1031                    open(reimport_file,"a").write(headline_for_reimport +'\n')                   
1032                format = '"%(' + ')s","%('.join(fields) + ')s"'
1033                format_for_reimport = '"%(' + ')s","%('.join(fields_for_reimport) + ')s"'
1034                res = self.students_catalog(id = student_id)
1035                student = res[0]
1036                student_obj = getattr(students_folder,student_id)
1037                #d = student.getFormattedStudentEntry(student)
1038                d = {'student_id':student_id,'reg_state':student.review_state,'import_mode':'create'}
1039                for k in toexport.keys()[0:]:
1040                    if k.startswith('acco'):
1041                        session = self.session
1042                        subobject = 'accommodation_' + session
1043                    else:
1044                        subobject = k
1045                    try:
1046                        object = getattr(student_obj,subobject)
1047                        object_doc = object.getContent()
1048                    except:
1049                        for f in toexport[k]:
1050                            d[f] = ''
1051                        continue
1052                    for f in toexport[k]:
1053                        d[f] = getattr(object_doc,f,'')
1054                if hasattr(stdir, student_id):
1055                    d['password'] = self.waeup_tool.getCredential(student_id)
1056                    stdir.deleteEntry(student_id)
1057                else:
1058                    d['password'] = "not set"
1059                self.waeup_tool.removePictureFolder(student_id)       
1060                line.append(format % d)
1061                open(export_file,"a").write('\n'.join(line) +'\n')
1062                line_for_reimport.append(format_for_reimport % d)
1063                open(reimport_file,"a").write('\n'.join(line_for_reimport) +'\n')               
1064                self.course_results.exportRemoveAllCourses(student_id = student_id, export = True, remove = True)
1065                # remove should be false, otherwise an uncatalog error occurs if payment objects exist
1066                self.payments_catalog.exportRemoveAllPayments(student_id = student_id, export = True, remove = False)
1067                self.waeup_tool.exportAllStudyLevels(student_id = student_id)
1068                # end export
1069                students_folder.manage_delObjects((student_id),) 
1070                try:
1071                    self.removed_student_ids.addRecord(id = student_id)
1072                except: 
1073                    msg = "Student already in removed_student_ids"
1074            else:
1075                msg = "Student object not found"
1076                break
1077     
1078            break
1079        return student_id,msg,mapping     
1080
1081
1082    def edit(self,mapping): ###(
1083        "edit student records due import"
1084        wftool = self.portal_workflow
1085        logger = logging.getLogger('WAeUPImport.StudentImport.edit')
1086        students_folder = self.portal_url.getPortalObject().campus.students
1087        student_id = mapping.get('id',None)
1088        jamb_reg_no = mapping.get('jamb_reg_no',None)
1089        matric_no = mapping.get('matric_no',None)
1090        editable_keys = mapping.keys()
1091        password = mapping.get('password',None)
1092        msg = ''
1093        while True:
1094            if student_id:
1095                res = self.students_catalog(id = student_id)
1096                if not res:
1097                    msg = "no student with id %s" % student_id
1098                    break
1099                student_record = res[0]
1100                if matric_no and student_record.matric_no:
1101                    if  matric_no != student_record.matric_no and not matric_no == 'transferred':
1102                        res = self.students_catalog(matric_no = matric_no)
1103                        if res:
1104                            msg = "matric_no already assigned to student %s" % res[0].id
1105                            break
1106                        msg = "old matric_no %s overwritten with %s" % (student_record.matric_no,matric_no)
1107                        #logger.info("%s, old matric_no %s overwritten with %s" % (student_record.id,student_record.matric_no,matric_no))
1108                if jamb_reg_no and student_record.jamb_reg_no:
1109                    if jamb_reg_no != student_record.jamb_reg_no:
1110                        res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1111                        if res:
1112                            msg = "jamb_reg_no already assigned to student %s" % res[0].id
1113                            break
1114                        msg = "old jamb_reg_no %s overwritten with %s" % (student_record.jamb_reg_no,jamb_reg_no)
1115                        #logger.info("%s, old reg_no %s overwritten with %s" % (student_record.id,student_record.jamb_reg_no,jamb_reg_no))
1116            elif jamb_reg_no:
1117                res = self.students_catalog(jamb_reg_no = jamb_reg_no)
1118                if not res:
1119                    msg = "no student with jamb_reg_no %s" % jamb_reg_no
1120                    break
1121                student_record = res[0]
1122                editable_keys.remove('jamb_reg_no')
1123            elif matric_no:
1124                res = self.students_catalog(matric_no = matric_no)
1125                if not res:
1126                    msg = "no student with matric_no %s" % matric_no
1127                    break
1128                student_record = res[0]
1129                editable_keys.remove('matric_no')
1130            student_id = student_record.id
1131            student_obj = getattr(students_folder,student_id)
1132            f2t = self.field2types_student
1133            d = {}
1134            any_change = False
1135            #special treatment for StudentStudyLevel
1136            d['verdict']  = mapping.get('current_verdict','')
1137            d['session']  = mapping.get('current_session','')
1138            current_level = mapping.get('current_level','')
1139            transition = mapping.get('reg_transition',None)
1140            change_reg_state = mapping.get('change_reg_state',None)  # for brute force method
1141            # the validate_courses import transition is not really useful because it does not execute validate_courses.py
1142            if transition and transition not in ('admit','return','graduate','pay_school_fee','validate_courses','reject_clearance'):
1143                msg = "no valid transition provided"
1144                break     
1145            while d['session'] and d['verdict'] and current_level:
1146                sub_obj = getattr(student_obj,'study_course',None)
1147                if sub_obj is None:
1148                    break
1149                level_obj = getattr(sub_obj,current_level,None)
1150                if  level_obj is None:
1151                    break
1152                any_change = True
1153                level_obj.getContent().edit(mapping = d)
1154                try:
1155                    wftool.doActionFor(level_obj,'close')
1156                except:
1157                    pass
1158                break
1159           
1160            for pt in f2t.keys():
1161                #if pt == "StudentApplication":
1162                #    d['jamb_sex']  = 'M'
1163                #    if mapping.get('sex'):
1164                #        d['jamb_sex']  = 'F'
1165                intersect = set(f2t[pt]['fields']).intersection(set(editable_keys))
1166                #import pdb;pdb.set_trace()
1167                object_id = f2t[pt]['id']
1168                sub_obj = getattr(student_obj,object_id,None)
1169                if intersect and pt not in ('StudentStudyLevel',):
1170                    if sub_obj is None:
1171                        try:
1172                            student_obj.invokeFactory(pt,object_id)
1173                        except:
1174                            continue
1175                        sub_obj = getattr(student_obj,object_id)
1176                        #if f2t[pt]['title'] != '':
1177                        #    d['Title'] = f2t[pt]['title']
1178                    sub_doc = sub_obj.getContent()
1179                    for field in intersect:
1180                        changed = False
1181                        if getattr(sub_doc,field,None) != mapping.get(field,''):
1182                            any_change = True
1183                            changed = True
1184                            d[field] = mapping.get(field,'')
1185                        if changed:
1186                            sub_doc.edit(mapping = d)
1187                if transition:
1188                    new_state = f2t[pt]['wf_transition_%(transition)s' % vars()]
1189                    if new_state != "remain":
1190                        try:
1191                            self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
1192                        except:
1193                            pass
1194            if transition:
1195                #import pdb;pdb.set_trace()
1196                try:
1197                    self.portal_workflow.doActionFor(student_obj,transition)
1198                except:
1199                    msg = "reg_transition not allowed"
1200            elif change_reg_state:
1201                msg = self.waeup_tool.changeStudentState(student_obj, change_reg_state)
1202             
1203            if password:
1204                self.waeup_tool.editPassword(student_id,password)
1205            break
1206        return student_id,msg,mapping
1207    ###)
1208###)
1209
1210class StudentStudyLevelImport(WAeUPImport):###(
1211    """ StudentStudyLevelImport """
1212    name = "student_study_level"
1213    plural_name = "%ss" % name
1214    commit_after = 1000
1215    required_modes = ('create',)
1216
1217    def create(self,mapping): ###(
1218        "edit student levels and create StudentStudyLevel object if not existent"
1219        wftool = self.portal_workflow
1220        logger = logging.getLogger('WAeUPImport.StudentStudyLevelImport.create')
1221        students_folder = self.portal_url.getPortalObject().campus.students
1222        student_id = mapping.get('id',None)
1223        matric_no = mapping.get('matric_no',None)
1224        editable_keys = mapping.keys()
1225        key = ''
1226        msg = ''
1227        while True:
1228            result = self.findStudent('create',student_id=student_id,matric_no=matric_no)
1229            msg = result['msg']
1230            if msg:
1231                break
1232            student_record = result['student_record']
1233            student_id = student_record.id
1234            mapping['id'] = student_id
1235            session = mapping.get('session','')
1236            level = key = mapping.get('code','')
1237            if not level.isdigit():
1238                msg = 'student %s: imported level is empty' % (student_id,)
1239                break
1240            study_course_obj = getattr(getattr(students_folder,student_id),'study_course',None)
1241            if study_course_obj is None:
1242                msg = 'student %s: no study_course object' % student_id
1243                break
1244            level_obj = getattr(study_course_obj,level,None)
1245            if  level_obj is None:
1246                # The only difference to the edit method is that we create a StudentStudyLevel object
1247                try:
1248                    study_course_obj.invokeFactory('StudentStudyLevel',"%s" % level)
1249                    level_obj = getattr(context,"%s" % level)
1250                except:
1251                    continue
1252            level_obj.getContent().edit(mapping = mapping)
1253            level_review_state = wftool.getInfoFor(level_obj,'review_state',None)
1254            if level_review_state != "closed":
1255                wftool.doActionFor(level_obj,'close')
1256            break
1257        return key,msg,mapping
1258    ###)
1259
1260    def edit(self,mapping): ###(
1261        "edit student levels"
1262        wftool = self.portal_workflow
1263        logger = logging.getLogger('WAeUPImport.StudentStudyLevelImport.edit')
1264        students_folder = self.portal_url.getPortalObject().campus.students
1265        student_id = mapping.get('id',None)
1266        matric_no = mapping.get('matric_no',None)
1267        key = ''
1268        msg = ''
1269        while True:
1270            result = self.findStudent('create',student_id=student_id,matric_no=matric_no)
1271            msg = result['msg']
1272            if msg:
1273                break
1274            student_record = result['student_record']
1275            student_id = student_record.id
1276            mapping['id'] = student_id
1277            session = mapping.get('session','')
1278            level = key = mapping.get('code','')
1279            #import pdb;pdb.set_trace()
1280            if not level.isdigit():
1281                msg = 'student %s: imported level is empty' % (student_id,)
1282                break
1283            study_course_obj = getattr(getattr(students_folder,student_id),'study_course',None)
1284            if study_course_obj is None:
1285                msg = 'student %s: no study_course object' % student_id
1286                break
1287            level_obj = getattr(study_course_obj,level,None)
1288            if  level_obj is None:
1289                msg = 'student %s: no study_level object for level %s' % (student_id,level)
1290                break
1291            level_obj.getContent().edit(mapping = mapping)
1292            break
1293        return key,msg,mapping
1294    ###)
1295###)
1296
1297class VerdictImport(WAeUPImport):###(
1298    """ VerdictImport """
1299    name = "verdict"
1300    plural_name = "%ss" % name
1301    commit_after = 1000
1302    required_modes = ('create','edit')
1303
1304    def create(self,mapping): ###(
1305        "edit student verdicts and create StudentStudyLevel object if not existent"
1306        wftool = self.portal_workflow
1307        logger = logging.getLogger('WAeUPImport.VerdictImport.create')
1308        students_folder = self.portal_url.getPortalObject().campus.students
1309        student_id = mapping.get('id',None)
1310        matric_no = mapping.get('matric_no',None)
1311        editable_keys = mapping.keys()
1312        key = ''
1313        while True:
1314            result = self.findStudent('create',student_id=student_id,matric_no=matric_no)
1315            #student_record,msg = self.getStudentRecord(mapping)
1316            msg = result['msg']
1317            if msg:
1318                break
1319            student_record = result['student_record']
1320            student_id = student_record.id
1321            mapping['id'] = student_id
1322            d = {}
1323            #import pdb;pdb.set_trace()
1324            any_change = False
1325            #special treatment for StudentStudyLevel
1326            current_session = d['session'] = mapping.get('current_session','')
1327            if current_session and student_record.session != current_session:
1328                msg = 'student %s: imported session %s does not match current_session %s' % (student_id,
1329                                                                                            current_session,
1330                                                                                            student_record.session)
1331                break
1332            current_level = mapping.get('current_level','')
1333            if not current_level.isdigit():
1334                msg = 'student %s: imported level is empty' % (student_id,)
1335                break
1336            if current_level and student_record.level != current_level:
1337                msg = 'student %s: imported level %s does not match current_level %s' % (student_id,
1338                                                                                        current_level,
1339                                                                                        student_record.level)
1340                break
1341            student_review_state =  student_record.review_state
1342            if student_review_state == 'deactivated':
1343                msg = "student %s in review_state %s" % (student_id, student_review_state)
1344                break
1345            if student_review_state not in ('courses_validated','returning'):
1346                msg = "student %s in wrong review_state %s" % (student_id, student_review_state)
1347                break
1348            student_obj = getattr(students_folder,student_id)
1349            # f2t = self.field2types_student
1350            study_course_obj = getattr(student_obj,'study_course',None)
1351            if study_course_obj is None:
1352                msg = 'student %s: no study_course object' % student_id
1353                break
1354            level_obj = getattr(study_course_obj,current_level,None)
1355
1356            if  level_obj is None:
1357                # The only difference to the edit method is that we create a StudentStudyLevel object
1358                try:
1359                    study_course_obj.invokeFactory('StudentStudyLevel',"%s" % current_level)
1360                    level_obj = getattr(context,"%s" % current_level)
1361                    level_obj.portal_workflow.doActionFor(level,'open')
1362                except:
1363                    continue
1364                #msg = 'student %s: no study_level object for level %s' % (student_id,
1365                #                                                                current_level)
1366                #break
1367
1368            verdict = d['verdict'] = d['current_verdict']  = mapping.get('current_verdict','')
1369
1370            #if verdict == student_record.verdict:
1371            #    msg = 'student %s: verdict already set to %s' % (student_id,
1372            #                                                            verdict)
1373
1374            level_review_state = wftool.getInfoFor(level_obj,'review_state',None)
1375            if level_review_state != "closed":
1376                wftool.doActionFor(level_obj,'close')
1377                # msg = 'student %s: level %s is not closed' % (student_id,
1378                #                                                      current_level)
1379
1380            study_course_obj.getContent().edit(mapping = d)
1381            level_obj.getContent().edit(mapping = d)
1382            if student_review_state != "returning":
1383                wftool.doActionFor(student_obj,'return')
1384            # try:
1385            #     wftool.doActionFor(level_obj,'close')
1386            # except:
1387            #     pass
1388            break
1389        return student_id,msg,mapping
1390    ###)
1391
1392
1393    def edit(self,mapping): ###(
1394        "edit student verdicts"
1395        wftool = self.portal_workflow
1396        logger = logging.getLogger('WAeUPImport.VerdictImport.edit')
1397        students_folder = self.portal_url.getPortalObject().campus.students
1398        student_id = mapping.get('id',None)
1399        matric_no = mapping.get('matric_no',None)
1400        editable_keys = mapping.keys()
1401        key = ''
1402        while True:
1403            result = self.findStudent('edit',student_id=student_id,matric_no=matric_no)
1404            #student_record,msg = self.getStudentRecord(mapping)
1405            msg = result['msg']
1406            if msg:
1407                break
1408            student_record = result['student_record']
1409            key_used = result['key_used']
1410            if key_used in editable_keys:
1411                editable_keys.remove(key_used)
1412            student_id = student_record.id
1413            mapping['id'] = student_id
1414            d = {}
1415            #import pdb;pdb.set_trace()
1416            any_change = False
1417            #special treatment for StudentStudyLevel
1418            current_session = d['session'] = mapping.get('current_session','')
1419            if current_session and student_record.session != current_session:
1420                msg = 'student %s: imported session %s does not match current_session %s' % (student_id,
1421                                                                                            current_session,
1422                                                                                            student_record.session)
1423                break
1424            current_level = mapping.get('current_level','')
1425            if not current_level.isdigit():
1426                msg = 'student %s: imported level is empty' % (student_id,)
1427                break
1428            if current_level and student_record.level != current_level:
1429                msg = 'student %s: imported level %s does not match current_level %s' % (student_id,
1430                                                                                        current_level,
1431                                                                                        student_record.level)
1432                break
1433            student_review_state =  student_record.review_state
1434            if student_review_state == 'deactivated':
1435                msg = "student %s in review_state %s" % (student_id, student_review_state)
1436                break
1437            if student_review_state not in ('courses_validated','returning'):
1438                msg = "student %s in wrong review_state %s" % (student_id, student_review_state)
1439                break
1440            student_obj = getattr(students_folder,student_id)
1441            # f2t = self.field2types_student
1442            study_course_obj = getattr(student_obj,'study_course',None)
1443            if study_course_obj is None:
1444                msg = 'student %s: no study_course object' % student_id
1445                break
1446            level_obj = getattr(study_course_obj,current_level,None)
1447            if  level_obj is None:
1448                msg = 'student %s: no study_level object for level %s' % (student_id,
1449                                                                                current_level)
1450                break
1451            verdict = d['verdict'] = d['current_verdict']  = mapping.get('current_verdict','')
1452
1453            #if verdict == student_record.verdict:
1454            #    msg = 'student %s: verdict already set to %s' % (student_id,
1455            #                                                            verdict)
1456
1457            level_review_state = wftool.getInfoFor(level_obj,'review_state',None)
1458            if level_review_state != "closed":
1459                #wftool.doActionFor(level_obj,'close')
1460                self.waeup_tool.changeWorkflowState(level_obj, 'closed')
1461                # msg = 'student %s: level %s is not closed' % (student_id,
1462                #                                                      current_level)
1463
1464            study_course_obj.getContent().edit(mapping = d)
1465            level_obj.getContent().edit(mapping = d)
1466            if student_review_state != "returning":
1467                #wftool.doActionFor(student_obj,'return')
1468                self.waeup_tool.changeStudentState(student_obj, 'returning')
1469            # try:
1470            #     wftool.doActionFor(level_obj,'close')
1471            # except:
1472            #     pass
1473            break
1474        return student_id,msg,mapping
1475    ###)
1476
1477   
1478   
1479class PaymentImport(WAeUPImport):###(
1480    """ PaymentImport """
1481    name = "payment"
1482    plural_name = "%ss" % name
1483    commit_after = 1000000
1484    required_modes = ('create',)
1485
1486    def create(self,mapping): ###(
1487        "create payment object"
1488        wftool = self.portal_workflow
1489        logger = logging.getLogger('WAeUPImport.PaymentImport.create')
1490        students_folder = self.portal_url.getPortalObject().campus.students
1491        student_id = mapping.get('id',None)
1492        order_id = key= mapping.get('order_id',None)
1493        payment_type = mapping.get('type',None)
1494        editable_keys = mapping.keys()
1495        key = ''
1496        msg = ''
1497        while True:
1498            result = self.findStudent('create',student_id=student_id)
1499            msg = result['msg']
1500            if msg:
1501                break           
1502            if payment_type == 'sc':
1503                hyphen = order_id.rfind('-')
1504                if not hyphen > -1:
1505                    msg = '%s: wrong order_id of sc payment' % student_id
1506                    break
1507                payment_object_id = 'p' + order_id[hyphen+1:]
1508            elif payment_type == 'online':
1509                payment_object_id = 'p' + order_id[6:]
1510            else:
1511                msg = '%s: no payment type defined' % student_id
1512                break
1513            student_record = result['student_record']
1514            student_id = student_record.id
1515
1516            mapping['id'] = student_id
1517            payments_folder = getattr(getattr(students_folder,student_id),'payments',None)
1518            if payments_folder is None:
1519                msg = '%s: no payments folder' % student_id
1520                break
1521            if getattr(payments_folder,payment_object_id,False):
1522                msg = '%s: payment object with id %s exists' % (student_id,payment_object_id)
1523                break
1524            try:
1525                #import pdb;pdb.set_trace()
1526                payments_folder.invokeFactory('Payment',"%s" % payment_object_id)
1527                payment_obj = getattr(payments_folder,"%s" % payment_object_id)
1528            except:
1529                msg = '%s: payment object %s cannot be created' % (student_id,payment_object_id)
1530                break
1531            payment_obj.getContent().edit(mapping = mapping)
1532            wftool.doActionFor(payment_obj,'close')
1533            break
1534        return key,msg,mapping
1535    ###)
1536   
1537   
1538   
1539    def remove(self,mapping):
1540        order_id = mapping.get('order_id')
1541        msg = ''
1542        while True:
1543            if self.payments_catalog.getRecordByKey(order_id) is None:
1544                msg =  "no payment record with order_id %(order_id)s" % vars()
1545                break
1546            self.payments_catalog.deleteRecord(order_id)
1547            break
1548        return order_id,msg,mapping       
1549   
1550   
1551###)
Note: See TracBrowser for help on using the repository browser.