source: WAeUP_SRP/base/WAeUPImport.py @ 3289

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

implemented new Upload functionallity

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