source: WAeUP_SRP/base/WAeUPImport.py @ 3253

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

fix for #93

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