source: WAeUP_SRP/base/WAeUPImport.py @ 3248

Last change on this file since 3248 was 3248, checked in by joachim, 17 years ago

check for required fields in item.

  • Property svn:keywords set to Id
File size: 45.8 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 3248 2008-02-28 08:03:50Z joachim $
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
28#from 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
35#from 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
40#from 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
53class WAeUPImport: ###(
54    """ WAeUPImport """
55    required_modes = ('create',)
56
57    def __init__(self,waeup_tool):
58        self.member = member = waeup_tool.portal_membership.getAuthenticatedMember()
59        self.import_date = DateTime.DateTime().strftime("%d/%m/%y %H:%M:%S")
60        self.current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
61        self.waeup_tool = waeup_tool
62        self.students_folder = waeup_tool.portal_url.getPortalObject().campus.students
63        self.academics_folder = waeup_tool.portal_url.getPortalObject().campus.academics
64        self.schema_tool = getToolByName(waeup_tool, 'portal_schemas')
65        self.layout_tool = getToolByName(waeup_tool, 'portal_layouts')
66        self.portal_workflow = getToolByName(waeup_tool, 'portal_workflow')
67        self.portal_url = getToolByName(waeup_tool, 'portal_url')
68        self.portal_catalog = waeup_tool.portal_catalog
69        self.students_catalog = waeup_tool.students_catalog
70        self.courses_catalog = waeup_tool.courses_catalog
71        self.course_results = waeup_tool.course_results
72        #self.mode = mode
73        # self.import_method = getattr(self, '%s' % mode,None)
74        errors = []
75        # if self.import_method is None:
76        #     errors.append('No importer method %s' % mode)
77        self.pending_path = "%s/import/%s.pending" % (i_home,self.plural_name)
78        self.pending_tmp = "%s/import/%s.pending.tmp" % (i_home,self.plural_name)
79        self.pending_backup = "%s/import/%s.pending.old" % (i_home,self.plural_name)
80        self.pending_fn = os.path.split(self.pending_path)[1]
81        self.imported_path = "%s/import/%s.imported" % (i_home,self.plural_name)
82        self.imported_fn = os.path.split(self.imported_path)[1]
83        iname = "import_%s" % self.name
84        self.logger = logging.getLogger('WAeUPTool.import%s' % self.plural_name.capitalize())
85        self.schema = self.schema_tool._getOb(iname,None)
86        self.pending_schema = self.schema_tool._getOb("%s_pending" % iname,None)
87        self.layout = self.layout_tool._getOb(iname,None)
88        if self.schema is None:
89            errors.append('no schema %s' % iname)
90        if self.pending_schema is None:
91            self.pending_schema = self.schema
92        if self.layout is None:
93            errors.append('no such layout %s' % iname)
94        self.data_keys = self.pending_schema.keys()
95        self.csv_keys = self.pending_schema.keys()
96        info = {}
97        info['imported_from'] = ''
98        info['imported_by'] = str(member)
99        info['import_date'] = self.import_date
100        #info['import_mode'] = mode #now in import_xxx schema + layout
101        info['error'] = ''
102        #info['digest'] = ''
103        self.info = info
104        self.csv_keys.extend(self.info)
105        self.validators = {}
106        for widget in self.layout.keys():
107            self.validators[widget] = self.layout[widget].validate
108        self.required_keys = {}
109        for mode in self.required_modes:
110            self.required_keys[mode] = [self.layout.getIdUnprefixed(id)
111                                for id,widget in self.layout.objectItems()
112                                if widget.is_required]
113        self.init_errors = ','.join(errors)
114
115    def makeIdLists(self):
116        pending_digests = []
117        pending = []
118        # pending_student_ids = []
119        # pending_matric_nos = []
120        # pending_reg_ns = []
121        if os.path.exists(self.pending_path):
122            datafile = open(self.pending_path,"r")
123            pending_csv_reader = csv.DictReader(datafile,self.csv_keys,)
124            pending_csv_reader.next() # skip headline
125            for item in pending_csv_reader:
126                digest = makeDigest(item,self.data_keys)
127                if digest not in pending_digests:
128                    pending_digests += digest,
129                    pending += item,
130            datafile.close()
131            copy2(self.pending_path,self.pending_backup)
132        return pending, pending_digests
133###)
134
135class ApplicationImport(WAeUPImport):###(
136    name = "applications"
137    plural_name = "%ss" % name
138    commit_after = 1000
139
140    def create(self,mapping):###(
141        reg_no = mapping.get('reg_no')
142        msg = ''
143        while True:
144            try:
145                self.applicants_catalog.addRecord(**mapping)
146            except ValueError:
147                msg =  "applicant record with reg_no %s already exists" % reg_no
148            break
149        return reg_no,msg,mapping
150    ###)
151
152    def edit(self,mapping):###(
153        reg_no = mapping.get('reg_no')
154        status = mapping.get('status')
155        msg = ''
156        while True:
157            res = self.applicants_catalog(reg_no = reg_no)
158            if len(res):
159                if res[0].status == 'created' and status != 'created':
160                    msg =  "student object with id %s for %s already created, status cannot be changed" % (res[0].student_id, reg_no)
161                elif status == 'created' and res[0].status != 'created':
162                    msg =  "student object for %s has not yet been created, status cannot be set to 'created'" % (reg_no)
163                else:
164                    self.applicants_catalog.modifyRecord(**mapping)
165            else:
166                msg =  "applicant record with reg_no %s does not exist" % reg_no
167            break
168        return reg_no,msg,mapping
169    ###)
170
171###)
172
173class CertificateImport(WAeUPImport):###(
174    name = "certificate"
175    plural_name = "%ss" % name
176    commit_after = 100000
177
178    def create(self,mapping):###(
179        if getattr(self,'_v_certificate_list',None) is None:
180            self._v_certificate_list = []
181        if getattr(self,'_v_department_certificates',None) is None:
182            departments = self.portal_catalog(portal_type = "Department")
183            self._v_department_certificates = {}
184            for d in departments:
185                certificates_folder = getattr(d.getObject(),"certificates",None)
186                self._v_department_certificates[d.getId] = certificates_folder.objectIds()
187        department_id = mapping['department_code']
188        msg = ''
189        certificate_id = mapping.get('code')
190        while True:
191            department_certificates = self._v_department_certificates.get(department_id,None)
192            if department_certificates is None:
193                msg =  "No Department with ID: %s" % department_id
194                break
195            if certificate_id in self._v_certificate_list:
196                msg =  "Duplicate Certificate ID: %s" % department_id
197                break
198            if certificate_id in department_certificates:
199                msg =  "Duplicate Certificate ID: %s" % department_id
200                break
201            try:
202                d.invokeFactory('Certificate', certificate_id)
203            except BadRequest,E:
204                msg =  "%s" % E
205                break
206            self._v_certificate_list.append(certificate_id)
207            c = getattr(d,certificate_id)
208            c.getContent().edit(mapping=mapping)
209            break
210        return certificate_id,msg,mapping
211    ###)
212
213    def edit(self,mapping):###(
214        certificate_id = mapping.get('code')
215        res = self.portal_catalog(id=certificate_id)
216        msg = ''
217        while True:
218            if not res:
219                msg =  "no certificate with id: %s" % certificate_id
220                break
221            c = res[0].getObject()
222            c.getContent().edit(mapping=mapping)
223            break
224        return certificate_id,msg,mapping
225    ###)
226###)
227
228class CourseImport(WAeUPImport):###(
229    name = "course"
230    plural_name = "%ss" % name
231    commit_after = 1000
232
233    def create(self,mapping):###(
234        if getattr(self,'_v_course_list',None) is None:
235            self._v_course_list = []
236        if getattr(self,'_v_department_courses',None) is None:
237            departments = self.portal_catalog(portal_type = "Department")
238            self._v_department_courses = {}
239            for department in departments:
240                courses_folder = getattr(department.getObject(),"courses",None)
241                if courses_folder is not None:
242                    self._v_department_courses[department.getId] = courses_folder.objectIds()
243        department_id = mapping['department_code']
244        course_id = mapping.get('code','')
245        msg = ''
246        while True:
247            department_courses = self._v_department_courses.get(department_id,None)
248            if department_courses is None:
249                msg =  "no department with id: %(department_id)s" % vars()
250                break
251            if course_id in self._v_course_list:
252                msg =  "duplicate course id: %(course_id)s" % vars()
253                break
254            if course_id in department_courses:
255                msg =  "course %(course_id)s already exists in department %(department_id)s" % vars()
256                break
257            try:
258                department.invokeFactory('Course', course_id)
259            except BadRequest,E:
260                msg =  "%s" % E
261                break
262            self._v_course_list.append(course_id)
263            course = getattr(department,course_id)
264            course.getContent().edit(mapping=mapping)
265            break
266        return course_id,msg,mapping
267    ###)
268
269    def edit(self,mapping): ###(
270        course_id = mapping.get('code','')
271        course = self.courses_catalog.getRecordByKey(course_id)
272        while True:
273            if course is None:
274                msg =  "no course with id: %s" % course_id
275                break
276            course_object = getattr(getattr(self.academics_folder,course.department),course_id)
277            course_object.getContent().edit(mapping=mapping)
278            break
279        return course_id,msg,mapping
280    ###)
281###)
282
283class CourseResultImport(WAeUPImport):###(
284    """ CourseresultImport """
285    name = "course_result"
286    plural_name = "%ss" % name
287    commit_after = 1000000
288    required_modes = ('create','edit','remove')
289
290    def getStudentRecord(self,mapping): ###(
291        id_field_found = False
292        msg = ''
293        student_record = None
294        id_count = 0
295        for id_key in ('id','matric_no'):
296            id_field = mapping.get(id_key,'')
297            if id_field:
298                id_count += 1
299                search_key = id_key
300                search_field = id_field
301        while True:
302            if id_count > 1:
303                msg = "both id and matric_no are provided"
304                break
305            elif id_count == 0:
306                msg = "neither id nor matric_no provided"
307                break
308            query = Eq(search_key,search_field)
309            res = self.students_catalog.evalAdvancedQuery(query)
310            if res:
311                student_record = res[0]
312                if search_key == "matric_no":
313                    mapping['id'] = student_record.id
314                elif search_key == "id":
315                    mapping['matric_no'] = student_record.matric_no
316            else:
317                msg = "no student with %(search_key)s %(search_field)s" % vars()
318            break
319        return student_record,msg
320    ###)
321
322    def create(self,mapping):###(
323        students_folder = self.portal_url.getPortalObject().campus.students
324        if getattr(self,'_v_courses',None) is None:
325            res = self.courses_catalog()
326            self._v_courses = {}
327            for brain in res:
328                self._v_courses[brain.code] = brain
329        if getattr(self,'_v_level_created',None) is None:
330            self._v_level_created = []
331        msg = ''
332        key = ''
333        while True:
334            course_id = mapping.get('code')
335            if course_id not in self._v_courses.keys():
336                msg = "no course with id: %s" % course_id
337                break
338            student_record,msg = self.getStudentRecord(mapping)
339            if msg:
340                break
341            student_id = student_record.id
342            level_id = mapping.get('level_id','')
343            code = mapping.get('code','')
344            if student_id not in self._v_level_created:
345                try:
346                    context = getattr(getattr(students_folder,
347                                            "%(student_id)s" % vars()),
348                                    'study_course')
349                except:
350                    msg = "could not create level %(level_id)s for %(student_id)s" % vars()
351                    break
352                if level_id not in context.objectIds():
353                    context.invokeFactory('StudentStudyLevel',"%(level_id)s" % vars())
354                    level = getattr(context,"%(level_id)s" % vars())
355                    self.portal_workflow.doActionFor(level,'open')
356                    # the session string must not be copied into the level object
357                    current_verdict = getattr(student_record,'current_verdict','')
358                    current_session = getattr(student_record,'current_session','')
359                    if current_verdict and student_record.current_level == level_id:
360                        level.getContent().edit(mapping={'verdict': "%s" %
361                                                        current_verdict,
362                                                        'session': "%s" %
363                                                        current_session,
364                                                        })
365                        self.portal_workflow.doActionFor(level,'close')
366                self._v_level_created += student_id,
367            mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % vars()
368            for k in ('semester','credits',):
369                mapping[k] = getattr(self._v_courses[course_id],k)
370            try:
371                self.course_results.addRecord(**mapping)
372            except ValueError:
373                msg = "course result already exists: %s" % key
374            break
375        return key,msg,mapping
376    ###)
377
378    def edit(self,mapping): ###(
379        msg = ''
380        key = ''
381        while True:
382            student_record,msg = self.getStudentRecord(mapping)
383            if msg:
384                break
385            level_id = mapping.get('level_id','')
386            code = mapping.get('code','')
387            code = mapping['code']
388            mapping['key'] = key = "%(student_id)s|%(level_id)s|%(code)s" % vars()
389            break
390        try:
391            self.course_results.modifyRecord(**mapping)
392        except KeyError:
393            msg = "no course result with key %s" % key
394        return key,msg,mapping
395    ###)
396
397    def remove(self,mapping):###(
398        key = ''
399        msg = ''
400        while True:
401            student_record,msg = self.getStudentRecord(mapping)
402            if msg:
403                break
404            student_id = student_record.id
405            level_id = mapping.get('level_id','')
406            code = mapping.get('code','')
407            key = "%(student_id)s|%(level_id)s|%(code)s" % vars()
408            if self.course_results.getRecordByKey(key) is None:
409                msg =  "no course result with key %(key)s" % vars()
410                break
411            self.course_results.deleteRecord(key)
412            break
413        return key,msg,mapping
414    ###)
415
416###)
417
418class CertificateCourseImport(WAeUPImport):###(
419    name = "certificate_course"
420    plural_name = "%ss" % name
421    commit_after = 100000
422    required_modes = ('create','edit')
423
424    def create(self,mapping):
425        if getattr(self,'_v_courses',None) is None:
426            res = self.courses_catalog()
427            self._v_courses= [course.code for course in res]
428        if getattr(self,'_v_ceritficates',None) is None:
429            res = self.portal_catalog(portal_type = "Certificate")
430            self._v_certificates = {}
431            for cert in res:
432                self._v_certificates[cert.getId] = cert.getObject()
433        msg = ''
434        while True:
435            certificate_course_id = mapping.get('code')
436            if certificate_course_id not in self._v_courses:
437                msg =  "no course with id: %s" % certificate_course_id
438                break
439            cert_id = mapping['certificate_code']
440            cert = self._v_certificates.get(cert_id,None)
441            if cert is None:
442                msg =  "no certificate with id: %s" % cert_id
443                break
444            level_id = mapping.get('level')
445            level = getattr(cert,level_id,None)
446            if level is None:
447                cert.invokeFactory('StudyLevel', level_id)
448                level = getattr(cert,level_id,None)
449            elif hasattr(level,certificate_course_id):
450                msg =  "duplicate certificate course id: %(certificate_course_id)s " % vars()
451                msg += "in %(cert_id)s/ %(level_id)s" % vars()
452                break
453            level.invokeFactory('CertificateCourse', certificate_course_id)
454            c = getattr(level,certificate_course_id)
455            c.getContent().edit(mapping=mapping)
456            break
457        return certificate_course_id,msg,mapping
458    ###)
459
460class DepartmentImport(WAeUPImport):###(
461    name = "department"
462    plural_name = "%ss" % name
463    commit_after = 1000
464
465    def create(self,mapping):###(
466        "create a department in the correct faculty"
467        faculty_id = mapping['faculty_code']
468        msg = ''
469        if getattr(self,'_v_faculties',None) is None:
470            res = self.portal_catalog(portal_type = "Department")
471            self._v_faculties = {}
472            for f in res:
473                self._v_faculties[f.getId] = f.getObject()
474        department_id = mapping.get('code','')
475        while True:
476            faculty = self._v_faculties.get(faculty_id,None)
477            if faculty is None:
478                msg =  "no faculty with id: %s" % faculty_id
479                break
480            else:
481                d = getattr(faculty,department_id,None)
482                if d is None or d.portal_type == "Faculty":
483                    try:
484                        faculty.invokeFactory('Department', department_id)
485                    except BadRequest,E:
486                        msg =  "%s" % E
487                        break
488                    d = getattr(faculty,department_id)
489                    d.invokeFactory('CoursesFolder','courses')
490                    courses = getattr(d,'courses')
491                    dict = {'Title': 'Courses'}
492                    courses.getContent().edit(mapping=dict)
493                    d.invokeFactory('CertificatesFolder','certificates')
494                    certificates = getattr(d,'certificates')
495                    dict = {'Title': 'Certificates'}
496                    certificates.getContent().edit(mapping=dict)
497                    d.getContent().edit(mapping=mapping)
498            break
499        return department_id,msg,mapping
500    ###)
501
502    def edit(self,mapping): ###(
503        "edit a department in the correct faculty"
504        academics_folder = self.portal_url.getPortalObject().campus.academics
505        faculty_id = mapping['faculty_code']
506        department_id = mapping.get('code','')
507        msg = ''
508        while True:
509            try:
510                d = getattr(getattr(academics_folder,faculty_id),department_id,None)
511            except KeyError:
512                msg =  "department %s or faculty %s wrong" % (department_id,faculty_id)
513                break
514            if d is None or d.portal_type == "Faculty":
515                msg =  "department %s not found" % (department_id)
516                break
517            d.getContent().edit(mapping=mapping)
518            break
519        return department_id,msg,mapping
520    ###)
521###)
522
523class FacultyImport(WAeUPImport):###(
524    name = "faculty"
525    plural_name = "faculties"
526    commit_after = 100
527
528    def create(self,mapping): ###(
529        "create a faculty"
530        academics_folder = self.portal_url.getPortalObject().campus.academics
531        faculty_id = mapping.get('code','')
532        msg = ''
533        while True:
534            if faculty_id in academics_folder.objectIds():
535                msg =  "faculty with id: %s exists" % faculty_id
536                break
537            logger.info('Creating Faculty %(code)s, %(title)s' % mapping)
538            try:
539                academics_folder.invokeFactory('Faculty', faculty_id)
540            except BadRequest,E:
541                msg =  "%s" % E
542                break
543            f = getattr(academics_folder,faculty_id,None)
544            f.getContent().edit(mapping=mapping)
545            break
546        return faculty_id,msg,mapping
547        ###)
548
549    def edit(self,mapping): ###(
550        "edit a faculty"
551        academics_folder = self.portal_url.getPortalObject().campus.academics
552        faculty_id = mapping['code']
553        msg = ''
554        while True:
555            f = getattr(academics_folder,faculty_id,None)
556            if f is None:
557                msg =  "faculty with id: %s does not exist" % faculty_id
558            f.getContent().edit(mapping=mapping)
559            break
560        return faculty_id,msg,mapping
561    ###)
562###)
563
564class StudentImport(WAeUPImport):###(
565    name = "student"
566    plural_name = "%ss" % name
567    commit_after = 100
568
569    field2types_student = {   ###(
570                      'StudentApplication':
571                          {'id': 'application',
572                           'title': 'Application Data',
573                           'wf_transition_return': 'close',
574                           'wf_transition_admit': 'remain',
575                           'fields':
576                             ('jamb_reg_no',
577                              'entry_mode',
578                              'entry_session',
579                              'jamb_score',
580                              'app_email',
581                              'jamb_age',
582                              'jamb_state',
583                              'jamb_lga',
584                              'jamb_sex',
585                              )
586                              },
587                      #'StudentPume':
588                      #    {'id': 'pume',
589                      #     'title': 'Pume Data',
590                      #     'wf_transition_return': 'close',
591                      #     'wf_transition_admit': 'close',
592                      #     'fields':
593                      #       ('pume_score',
594                      #        )
595                      #        },
596                      'StudentClearance':
597                          {'id': 'clearance',
598                           'title': 'Clearance/Eligibility Record',
599                           'wf_transition_return': 'close',
600                           'wf_transition_admit': 'remain',
601                           'fields':
602                             ('matric_no',
603                              'nationality',
604                              'lga',
605                              'birthday',
606                              )
607                              },
608                         'StudentPersonal':
609                          {'id': 'personal',
610                           'title': 'Personal Data',
611                           'wf_transition_return': 'open',
612                           'wf_transition_admit': 'remain',
613                           'fields':
614                             ('firstname',
615                              'middlename',
616                              'lastname',
617                              'sex',
618                              'email',
619                              'phone',
620                              'perm_address',
621                              )
622                              },
623                         'StudentStudyCourse':
624                          {'id': 'study_course',
625                           'title': 'Study Course',
626                           'wf_transition_return': 'open',
627                           'wf_transition_admit': 'remain',
628                           'fields':
629                             ('study_course',
630                              'current_level',
631                              'current_session',
632                              'current_mode',
633                              'current_verdict',
634                              'previous_verdict',
635                              )
636                              },
637                         # 'StudentStudyLevel':
638                         #  {'id': 'current_level',
639                         #   'title': '',
640                         #   'wf_transition_return': 'open',
641                         #   'wf_transition_admit': 'remain',
642                         #   'fields':
643                         #     ('verdict',
644                         #      'session',
645                         #      )
646                         #      },
647                         'PaymentsFolder':
648                          {'id': 'payments',
649                           'title': 'Payments',
650                           'wf_transition_return': 'open',
651                           'wf_transition_admit': 'open',
652                           'fields':
653                             ()
654                              },
655                         }
656    ###)
657
658    def create(self,mapping): ###(
659        "create student records due import"
660        logger = logging.getLogger('WAeUPTool.mass_create_student')
661        students_folder = self.portal_url.getPortalObject().campus.students
662        jamb_reg_no = mapping.get('jamb_reg_no',None)
663        matric_no = mapping.get('matric_no',None)
664        msg = ''
665        student_id = mapping.get('id',None)
666        while True:
667            if student_id:
668                msg = "student_id must not be specified in create mode"
669                break
670            if jamb_reg_no:
671                res = self.students_catalog(jamb_reg_no = jamb_reg_no)
672                if res:
673                    msg = "jamb_reg_no exists"
674                    break
675            if matric_no:
676                res = self.students_catalog(matric_no = matric_no)
677                if res:
678                    msg = "matric_no exists"
679                    break
680            if not matric_no and not jamb_reg_no:
681                msg = "jamb_reg_no or matric_no must be specified"
682                break
683            student_id = self.waeup_tool.generateStudentId('?')
684            students_folder.invokeFactory('Student', student_id)
685            student_obj = getattr(students_folder,student_id)
686            f2t = self.field2types_student
687            d = {}
688            transition = mapping.get('reg_transition','admit')
689            if transition not in ('admit','return'):
690                msg = "no valid transition provided"
691                break
692            for pt in f2t.keys():
693                student_obj.invokeFactory(pt,f2t[pt]['id'])
694                sub_obj = getattr(student_obj,f2t[pt]['id'])
695                sub_doc = sub_obj.getContent()
696                d['Title'] = f2t[pt]['title']
697                for field in f2t[pt]['fields']:
698                    d[field] = mapping.get(field,'')
699
700                if pt == "StudentApplication":
701                    #d['jamb_sex']  = 'M'
702                    #if mapping.get('sex'):
703                    #    d['jamb_sex']  = 'F'
704                    d['jamb_firstname'] = mapping.get('firstname',None)
705                    d['jamb_middlename'] = mapping.get('middlename',None)
706                    d['jamb_lastname'] = mapping.get('lastname',None)
707
708                # if pt == "StudyCourse":
709                #     for von,zu in (('entry_mode','current_mode'),
710                #                    ('entry_session','current_session')):
711                #         if mapping.get(zu,None) is None and mapping.get(von,None) is not None:
712                #             d[zu] = mapping[von]
713                sub_doc.edit(mapping = d)
714
715                #import pdb;pdb.set_trace()
716                new_state = f2t[pt]['wf_transition_%(transition)s' % vars()]
717                if new_state != "remain":
718                    self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
719            self.portal_workflow.doActionFor(student_obj,transition)
720            student_obj.manage_setLocalRoles(student_id, ['Owner',])
721            mapping['id'] = student_id
722            break
723        return student_id,msg,mapping
724    ###)
725
726    def edit(self,mapping): ###(
727        wftool = self.portal_workflow
728        "edit student records due import"
729        logger = logging.getLogger('WAeUPTool.mass_edit_student')
730        students_folder = self.portal_url.getPortalObject().campus.students
731        student_id = mapping.get('id',None)
732        jamb_reg_no = mapping.get('jamb_reg_no',None)
733        matric_no = mapping.get('matric_no',None)
734        editable_keys = mapping.keys()
735        msg = ''
736        while True:
737            if student_id:
738                res = self.students_catalog(id = student_id)
739                if not res:
740                    msg = "no student with id %s" % student_id
741                    break
742                student_record = res[0]
743                if matric_no and student_record.matric_no:
744                    if  matric_no != student_record.matric_no:
745                        msg = "old matric_no %s overwritten with %s" % (student_record.matric_no,matric_no)
746                        #logger.info("%s, old matric_no %s overwritten with %s" % (student_record.id,student_record.matric_no,matric_no))
747                if jamb_reg_no and student_record.jamb_reg_no:
748                    if jamb_reg_no != student_record.jamb_reg_no:
749                        msg = "old reg_no %s overwritten with %s" % (student_record.jamb_reg_no,jamb_reg_no)
750                        #logger.info("%s, old reg_no %s overwritten with %s" % (student_record.id,student_record.jamb_reg_no,jamb_reg_no))
751            elif jamb_reg_no:
752                res = self.students_catalog(jamb_reg_no = jamb_reg_no)
753                if not res:
754                    msg = "no student with jamb_reg_no %s" % jamb_reg_no
755                    break
756                student_record = res[0]
757                editable_keys.remove('jamb_reg_no')
758            elif matric_no:
759                res = self.students_catalog(matric_no = matric_no)
760                if not res:
761                    msg = "no student with matric_no %s" % matric_no
762                    break
763                student_record = res[0]
764                editable_keys.remove('matric_no')
765            ## included only to change wf state from admitted to returning
766            #if student_record.review_state not in ('admitted','objection_raised'):
767            #    return '%s' % student_record.id ,"student is not in state admitted or objection_raised"
768            ## end inclusion
769            student_id = student_record.id
770            student_obj = getattr(students_folder,student_id)
771            f2t = self.field2types_student
772            d = {}
773            any_change = False
774            #special treatment for StudentStudyLevel
775            d['verdict']  = mapping.get('current_verdict','')
776            d['session']  = mapping.get('current_session','')
777            current_level = mapping.get('current_level','')
778            while d['session'] and d['verdict'] and current_level:
779                sub_obj = getattr(student_obj,'study_course',None)
780                if sub_obj is None:
781                    break
782                level_obj = getattr(sub_obj,current_level,None)
783                if  level_obj is None:
784                    break
785                any_change = True
786                level_obj.getContent().edit(mapping = d)
787                try:
788                    wftool.doActionFor(level_obj,'close')
789                except:
790                    pass
791                break
792            for pt in f2t.keys():
793                #if pt == "StudentApplication":
794                #    d['jamb_sex']  = 'M'
795                #    if mapping.get('sex'):
796                #        d['jamb_sex']  = 'F'
797                intersect = set(f2t[pt]['fields']).intersection(set(editable_keys))
798                if intersect and pt not in ('StudentStudyLevel',):
799                    object_id = f2t[pt]['id']
800                    sub_obj = getattr(student_obj,object_id,None)
801                    if sub_obj is None:
802                        try:
803                            student_obj.invokeFactory(pt,object_id)
804                        except:
805                            continue
806                        sub_obj = getattr(student_obj,object_id)
807                        if f2t[pt]['title'] != '':
808                            d['Title'] = f2t[pt]['title']
809                    sub_doc = sub_obj.getContent()
810                    for field in intersect:
811                        changed = False
812                        if getattr(sub_doc,field,None) != mapping.get(field,''):
813                            any_change = True
814                            changed = True
815                            d[field] = mapping.get(field,'')
816                        if changed:
817                            sub_doc.edit(mapping = d)
818            ## included only to change wf state from admitted to returning
819            #    if student_record.review_state in ('admitted','objection_raised'):
820            #        new_state = f2t[pt]['wf_transition_return']
821            #        sub_obj = getattr(student_obj,f2t[pt]['id'],None)
822            #        if sub_obj and new_state != "remain":
823            #            try:
824            #                self.portal_workflow.doActionFor(sub_obj,new_state,dest_container=sub_obj)
825            #            except:
826            #                #logger.info('%s, wf transition %s of %s failed' % (student_id,new_state,sub_obj.id))
827            #                pass
828            #if student_record.review_state in ('admitted','objection_raised'):
829            #    wfaction = 'return'
830            #    try:
831            #        self.portal_workflow.doActionFor(student_obj,wfaction)
832            #        logger.info('%s, wf state changed' % student_id)
833            #        any_change = True
834            #    except:
835            #        logger.info('%s, wf transition failed, old state = %s' % (student_id,student_record.review_state))
836            #        pass
837            ## end inclusion
838            break
839        # if not any_change:
840        #     msg = 'not modified'
841        return student_id,msg,mapping
842    ###)
843###)
844
845class VerdictImport(WAeUPImport):###(
846    """ VerdictImport """
847    name = "verdict"
848    plural_name = "%ss" % name
849    commit_after = 100000
850    required_modes = ('create','edit')
851   
852    def create(self,mapping):
853        "edit student verdicts and create StudentStudyLevel object if not existent"
854        wftool = self.portal_workflow
855        logger = logging.getLogger('WAeUPTool.mass_edit_verdict')
856        students_folder = self.portal_url.getPortalObject().campus.students
857        student_id = mapping.get('id',None)
858        matric_no = mapping.get('matric_no',None)
859        editable_keys = mapping.keys()
860        while True:
861            key = ''
862            msg = ''
863            if student_id:
864                student_record = self.students_catalog.getRecordByKey(student_id)
865                if student_record is None:
866                    #return '',"no student with id %s" % student_id
867                    msg = "no student with id %s" % student_id
868                    break
869                if matric_no and student_record.matric_no and matric_no != student_record.matric_no:
870                    msg = 'student %s: matric_no %s does not match %s' % (student_record.id,
871                                                                          student_record.matric_no,
872                                                                          matric_no)
873                    break
874                mapping['matric_no'] = student_record.matric_no
875            elif matric_no:
876                res = self.students_catalog(matric_no = matric_no)
877                if not res:
878                    msg = "no student with matric_no %s" % matric_no
879                    break
880                student_record = res[0]
881                editable_keys.remove('matric_no')
882            else:
883                msg = "no id or matric_no specified"
884                break
885            student_id = student_record.id
886            mapping['id'] = student_id
887            d = {}
888            #import pdb;pdb.set_trace()
889            any_change = False
890            #special treatment for StudentStudyLevel
891            current_session = d['session'] = mapping.get('current_session','')
892            if current_session and student_record.session != current_session:
893                msg = 'student %s: imported session %s does not match current_session %s' % (student_id,
894                                                                                            current_session,
895                                                                                            student_record.session)
896                break
897            current_level = mapping.get('current_level','')
898            if not current_level.isdigit():
899                msg = 'student %s: imported level is empty' % (student_id,)
900                break
901            if current_level and student_record.level != current_level:
902                msg = 'student %s: imported level %s does not match current_level %s' % (student_id,
903                                                                                        current_level,
904                                                                                        student_record.level)
905                break
906            student_review_state =  student_record.review_state
907            if student_review_state == 'deactivated':
908                msg = "student %s in review_state %s" % (student_id, student_review_state)
909                break
910            if student_review_state not in ('courses_validated','returning'):
911                msg = "student %s in wrong review_state %s" % (student_id, student_review_state)
912                break
913            student_obj = getattr(students_folder,student_id)
914            # f2t = self.field2types_student
915            study_course_obj = getattr(student_obj,'study_course',None)
916            if study_course_obj is None:
917                msg = 'student %s: no study_course object' % student_id
918                break
919            level_obj = getattr(study_course_obj,current_level,None)
920
921            if  level_obj is None:
922                # The only difference to the edit method is that we create a StudentStudyLevel object
923                try:
924                    study_course_obj.invokeFactory('StudentStudyLevel',"%s" % current_level)
925                    level_obj = getattr(context,"%s" % current_level)
926                    level_obj.portal_workflow.doActionFor(level,'open')
927                except:
928                    continue             
929                #msg = 'student %s: no study_level object for level %s' % (student_id,
930                #                                                                current_level)
931                #break
932
933            verdict = d['verdict'] = d['current_verdict']  = mapping.get('current_verdict','')
934
935            #if verdict == student_record.verdict:
936            #    msg = 'student %s: verdict already set to %s' % (student_id,
937            #                                                            verdict)
938
939            level_review_state = wftool.getInfoFor(level_obj,'review_state',None)
940            if level_review_state != "closed":
941                wftool.doActionFor(level_obj,'close')
942                # msg = 'student %s: level %s is not closed' % (student_id,
943                #                                                      current_level)
944
945            study_course_obj.getContent().edit(mapping = d)
946            level_obj.getContent().edit(mapping = d)
947            if student_review_state != "returning":
948                wftool.doActionFor(student_obj,'return')
949            # try:
950            #     wftool.doActionFor(level_obj,'close')
951            # except:
952            #     pass
953            break
954        return student_id,msg,mapping   
955
956
957    def edit(self,mapping):
958        "edit student verdicts"
959        wftool = self.portal_workflow
960        logger = logging.getLogger('WAeUPTool.mass_edit_verdict')
961        students_folder = self.portal_url.getPortalObject().campus.students
962        student_id = mapping.get('id',None)
963        matric_no = mapping.get('matric_no',None)
964        editable_keys = mapping.keys()
965        while True:
966            key = ''
967            msg = ''
968            if student_id:
969                student_record = self.students_catalog.getRecordByKey(student_id)
970                if student_record is None:
971                    #return '',"no student with id %s" % student_id
972                    msg = "no student with id %s" % student_id
973                    break
974                if matric_no and student_record.matric_no and matric_no != student_record.matric_no:
975                    msg = 'student %s: matric_no %s does not match %s' % (student_record.id,
976                                                                          student_record.matric_no,
977                                                                          matric_no)
978                    break
979                mapping['matric_no'] = student_record.matric_no
980            elif matric_no:
981                res = self.students_catalog(matric_no = matric_no)
982                if not res:
983                    msg = "no student with matric_no %s" % matric_no
984                    break
985                student_record = res[0]
986                editable_keys.remove('matric_no')
987            else:
988                msg = "no id or matric_no specified"
989                break
990            student_id = student_record.id
991            mapping['id'] = student_id
992            d = {}
993            #import pdb;pdb.set_trace()
994            any_change = False
995            #special treatment for StudentStudyLevel
996            current_session = d['session'] = mapping.get('current_session','')
997            if current_session and student_record.session != current_session:
998                msg = 'student %s: imported session %s does not match current_session %s' % (student_id,
999                                                                                            current_session,
1000                                                                                            student_record.session)
1001                break
1002            current_level = mapping.get('current_level','')
1003            if not current_level.isdigit():
1004                msg = 'student %s: imported level is empty' % (student_id,)
1005                break
1006            if current_level and student_record.level != current_level:
1007                msg = 'student %s: imported level %s does not match current_level %s' % (student_id,
1008                                                                                        current_level,
1009                                                                                        student_record.level)
1010                break
1011            student_review_state =  student_record.review_state
1012            if student_review_state == 'deactivated':
1013                msg = "student %s in review_state %s" % (student_id, student_review_state)
1014                break
1015            if student_review_state not in ('courses_validated','returning'):
1016                msg = "student %s in wrong review_state %s" % (student_id, student_review_state)
1017                break
1018            student_obj = getattr(students_folder,student_id)
1019            # f2t = self.field2types_student
1020            study_course_obj = getattr(student_obj,'study_course',None)
1021            if study_course_obj is None:
1022                msg = 'student %s: no study_course object' % student_id
1023                break
1024            level_obj = getattr(study_course_obj,current_level,None)
1025            if  level_obj is None:
1026                msg = 'student %s: no study_level object for level %s' % (student_id,
1027                                                                                current_level)
1028                break
1029            verdict = d['verdict'] = d['current_verdict']  = mapping.get('current_verdict','')
1030
1031            #if verdict == student_record.verdict:
1032            #    msg = 'student %s: verdict already set to %s' % (student_id,
1033            #                                                            verdict)
1034
1035            level_review_state = wftool.getInfoFor(level_obj,'review_state',None)
1036            if level_review_state != "closed":
1037                wftool.doActionFor(level_obj,'close')
1038                # msg = 'student %s: level %s is not closed' % (student_id,
1039                #                                                      current_level)
1040
1041            study_course_obj.getContent().edit(mapping = d)
1042            level_obj.getContent().edit(mapping = d)
1043            if student_review_state != "returning":
1044                wftool.doActionFor(student_obj,'return')
1045            # try:
1046            #     wftool.doActionFor(level_obj,'close')
1047            # except:
1048            #     pass
1049            break
1050        return student_id,msg,mapping
1051    ###)
1052
Note: See TracBrowser for help on using the repository browser.