source: WAeUP_SRP/trunk/WAeUPTables.py @ 2089

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

add course_results catalog

  • Property svn:keywords set to Id
File size: 37.7 KB
RevLine 
[966]1#-*- mode: python; mode: fold -*-
[363]2# (C) Copyright 2005 AixtraWare <http://aixtraware.de>
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: WAeUPTables.py 2084 2007-08-03 05:58:51Z joachim $
20
21from zope.interface import implements
22from Globals import InitializeClass
23from Products.ZCatalog.ZCatalog import ZCatalog
[1620]24from Products.ZCatalog.ProgressHandler import ZLogHandler
[780]25from AccessControl import ClassSecurityInfo
26from Products.CMFCore.permissions import ModifyPortalContent
[1700]27import urllib
[1620]28import DateTime,time
[780]29import csv,re
30import logging
31import Globals
32p_home = Globals.package_home(globals())
33i_home = Globals.INSTANCE_HOME
[1845]34from Products.CMFCore.CatalogTool import CatalogTool
[1702]35from Products.AdvancedQuery import Eq, Between, Le,In
[780]36
[2084]37ADDING_SHEDULED = "adding_sheduled"
38OBJECT_CREATED = "object_created"
39
[363]40from interfaces import IWAeUPTable
41
42class AttributeHolder(object):
43    pass
44
45def dict2ob(dict):
46    ob = AttributeHolder()
47    for key, value in dict.items():
48        setattr(ob, key, value)
49    return ob
50
[1146]51class WAeUPTable(ZCatalog): ###(
[834]52
[363]53    implements(IWAeUPTable)
[780]54    security = ClassSecurityInfo()
[834]55
[1620]56    def refreshCatalog(self, clear=0, pghandler=None):
57        """ don't refresh for a normal table """
58
59        if self.REQUEST and self.REQUEST.RESPONSE:
60            self.REQUEST.RESPONSE.redirect(
61              URL1 +
62              '/manage_catalogAdvanced?manage_tabs_message=Catalog%20refresh%20not%20implemented')
63
64    def manage_catalogClear(self, REQUEST=None, RESPONSE=None, URL1=None):
65        """ clears the whole enchilada """
[1986]66
[1916]67        #if REQUEST and RESPONSE:
68        #    RESPONSE.redirect(
69        #      URL1 +
70        #      '/manage_catalogAdvanced?manage_tabs_message=Catalog%20Clearing%20disabled')
[1620]71
[1916]72        self._catalog.clear()
[1620]73        if REQUEST and RESPONSE:
74            RESPONSE.redirect(
75              URL1 +
[1916]76              '/manage_catalogAdvanced?manage_tabs_message=Catalog%20cleared')
[1620]77
[363]78    def addRecord(self, **data):
[502]79        # The uid is the same as "bed".
80        uid = data[self.key]
81        res = self.searchResults({"%s" % self.key : uid})
82        if len(res) > 0:
83            raise ValueError("More than one record with uid %s" % uid)
84        self.catalog_object(dict2ob(data), uid=uid)
85        return uid
[834]86
[363]87    def deleteRecord(self, uid):
88        self.uncatalog_object(uid)
[834]89
[502]90    def searchAndSetRecord(self, **data):
91        raise NotImplemented
92
[2069]93    def modifyRecord(self, record=None, **data):
[502]94        #records = self.searchResults(uid=uid)
95        uid = data[self.key]
[2069]96        if record is None:
97            records = self.searchResults({"%s" % self.key : uid})
98            if len(records) > 1:
99                # Can not happen, but anyway...
100                raise ValueError("More than one record with uid %s" % uid)
101            if len(records) == 0:
102                raise KeyError("No record for uid %s" % uid)
103            record = records[0]
[363]104        record_data = {}
105        for field in self.schema() + self.indexes():
106            record_data[field] = getattr(record, field)
107        # Add the updated data:
108        record_data.update(data)
109        self.catalog_object(dict2ob(record_data), uid)
110
[1062]111    def reindexIndex(self, name, REQUEST,pghandler=None):
112        if isinstance(name, str):
113            name = (name,)
114        paths = self._catalog.uids.items()
115        i = 0
116        #import pdb;pdb.set_trace()
117        for p,rid in paths:
118            i += 1
119            metadata = self.getMetadataForRID(rid)
120            record_data = {}
121            for field in name:
122                record_data[field] = metadata.get(field)
123            uid = metadata.get(self.key)
124            self.catalog_object(dict2ob(record_data), uid, idxs=name,
125                                update_metadata=0)
[1082]126
[780]127    security.declareProtected(ModifyPortalContent,"exportAllRecords")
128    def exportAllRecords(self):
129        "export a WAeUPTable"
130        #import pdb;pdb.set_trace()
131        fields = [field for field in self.schema()]
132        format = ','.join(['"%%(%s)s"' % fn for fn in fields])
133        csv = []
134        csv.append(','.join(['"%s"' % fn for fn in fields]))
135        for uid in self._catalog.uids:
136            records = self.searchResults({"%s" % self.key : uid})
137            if len(records) > 1:
138                # Can not happen, but anyway...
139                raise ValueError("More than one record with uid %s" % uid)
140            if len(records) == 0:
141                raise KeyError("No record for uid %s" % uid)
142            rec = records[0]
143            csv.append(format % rec)
144        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
145        open("%s/import/%s-%s.csv" % (i_home,self.getId(),current),"w+").write('\n'.join(csv))
[1935]146    ###)
[834]147
[1146]148class AccommodationTable(WAeUPTable): ###(
[834]149
[404]150    meta_type = 'WAeUP Accommodation Tool'
[502]151    name = "accommodation"
152    key = "bed"
[363]153    def __init__(self):
[404]154        WAeUPTable.__init__(self, 'portal_accommodation')
[363]155
[635]156    def searchAndReserveBed(self, student_id,bed_type):
157        records = self.searchResults({'student' : student_id})
158        if len(records) > 0:
[1293]159            return -1,"Student with Id %s already booked bed %s." % (student_id,records[0].bed)
[834]160
[673]161        records = [r for r in self.searchResults({'bed_type' : bed_type}) if not r.student]
[686]162        #import pdb;pdb.set_trace()
[635]163        if len(records) == 0:
[1306]164            return -2,"No bed available"
[635]165        rec = records[0]
166        self.modifyRecord(bed=rec.bed,student=student_id)
[1571]167        s_logger = logging.getLogger('WAeUPTables.AccommodationTable.searchAndReserveBed')
168        s_logger.info('%s reserved bed %s' % (student_id,rec.bed))
[635]169        return 1,rec.bed
[363]170
[834]171
[404]172InitializeClass(AccommodationTable)
[411]173
[1146]174###)
175
176class PinTable(WAeUPTable): ###(
[1030]177    from ZODB.POSException import ConflictError
[440]178    meta_type = 'WAeUP Pin Tool'
[502]179    name = "pins"
180    key = 'pin'
[440]181    def __init__(self):
182        WAeUPTable.__init__(self, 'portal_pins')
[1082]183
184
[710]185    def searchAndSetRecord(self, uid, student_id,prefix):
[502]186        #records = self.searchResults(uid=uid)
[710]187        records = self.searchResults(student = student_id)
[990]188        #import pdb;pdb.set_trace()
[1776]189        if len(records) > 0 and prefix in ('CLR','APP'):
[710]190            for r in records:
[834]191                if r.pin != uid and r.prefix_batch.startswith(prefix):
[710]192                    return -2
[502]193        records = self.searchResults({"%s" % self.key : uid})
194        if len(records) > 1:
195            # Can not happen, but anyway...
196            raise ValueError("More than one record with uid %s" % uid)
197        if len(records) == 0:
198            return -1
199        record = records[0]
200        if record.student == "":
201            record_data = {}
202            for field in self.schema() + self.indexes():
203                record_data[field] = getattr(record, field)
204            # Add the updated data:
[635]205            record_data['student'] = student_id
[1030]206            try:
207                self.catalog_object(dict2ob(record_data), uid)
208                return 1
209            except ConflictError:
210                return 2
[990]211        if record.student.upper() != student_id.upper():
[502]212            return 0
[997]213        if record.student.upper() == student_id.upper():
[502]214            return 2
[997]215        return -3
[440]216
217InitializeClass(PinTable)
218
[1146]219###)
[966]220
[1146]221class PumeResultsTable(WAeUPTable): ###(
222
[966]223    meta_type = 'WAeUP PumeResults Tool'
224    name = "pumeresults"
225    key = "jamb_reg_no"
226    def __init__(self):
227        WAeUPTable.__init__(self, 'portal_pumeresults')
228
229
230InitializeClass(PumeResultsTable)
231
[1146]232###)
[971]233
[1146]234class StudentsCatalog(WAeUPTable): ###(
[1620]235    security = ClassSecurityInfo()
[1146]236
[971]237    meta_type = 'WAeUP Students Catalog'
238    name = "students_catalog"
239    key = "id"
[1700]240    affected_types = {   ###(
[1749]241                      'StudentApplication':
[2069]242                      {'id': 'application',
243                       'fields':
244                       ('jamb_reg_no',
245                        'entry_mode',
246                        #'entry_level',
247                        'entry_session',
248                       )
249                      },
[1700]250                      'StudentClearance':
[2069]251                      {'id': 'clearance',
252                       'fields':
253                       ('matric_no',
254                        'lga',
255                       )
256                      },
257                      'StudentPersonal':
258                      {'id': 'personal',
259                       'fields':
260                       ('name',
261                        'sex',
262                        'perm_address',
263                        'email',
264                        'phone',
265                       )
266                      },
267                      'StudentStudyCourse':
268                      {'id': 'study_course',
269                       'fields':
270                       ('course', # study_course
271                        'faculty', # from certificate
272                        'department', # from certificate
273                        'end_level', # from certificate
274                        'level', # current_level
275                        'mode',  # current_mode
276                        'session', # current_session
277                        'verdict', # current_verdict
278                       )
279                      },
280                     }
[1700]281    ###)
[1625]282
[971]283    def __init__(self):
284        WAeUPTable.__init__(self, 'students_catalog')
[1620]285        return
[1625]286
[1700]287    def manage_catalogClear(self, REQUEST=None, RESPONSE=None, URL1=None):
288        """ clears the whole enchilada """
289        self._catalog.clear()
[971]290
[1700]291        if REQUEST and RESPONSE:
292            RESPONSE.redirect(
293              URL1 +
294              '/manage_catalogAdvanced?manage_tabs_message=Catalog%20Cleared')
[971]295
[1700]296    def manage_catalogReindex(self, REQUEST, RESPONSE, URL1): ###(
297        """ clear the catalog, then re-index everything """
298
299        elapse = time.time()
300        c_elapse = time.clock()
301
302        pgthreshold = self._getProgressThreshold()
303        handler = (pgthreshold > 0) and ZLogHandler(pgthreshold) or None
304        self.refreshCatalog(clear=1, pghandler=handler)
305
306        elapse = time.time() - elapse
307        c_elapse = time.clock() - c_elapse
308
309        RESPONSE.redirect(
310            URL1 +
311            '/manage_catalogAdvanced?manage_tabs_message=' +
312            urllib.quote('Catalog Updated \n'
313                         'Total time: %s\n'
314                         'Total CPU time: %s' % (`elapse`, `c_elapse`)))
315    ###)
316
[2084]317    def fill_certificates_dict(self): ###(
[2078]318        "return certificate data in  dict"
319        certificates_brains = self.portal_catalog(portal_type ='Certificate')
320        d = {}
321        for cb in certificates_brains:
322            certificate_doc = cb.getObject().getContent()
323            cb_path = cb.getPath().split('/')
324            ld = {}
325            ld['faculty'] = cb_path[-4]
326            ld['department'] = cb_path[-3]
327            ld['end_level'] = getattr(certificate_doc,'end_level','999')
328            d[cb.getId] = ld
329        return d
[2084]330    ###)
331
[2078]332    def get_from_doc_department(self,doc,cached_data={}): ###(
[1620]333        "return the students department"
[1700]334        if doc is None:
[1620]335            return None
[2078]336        if cached_data.has_key(doc.study_course):
337            return cached_data[doc.study_course]['department']
[1700]338        certificate_res = self.portal_catalog(id = doc.study_course)
[1620]339        if len(certificate_res) != 1:
340            return None
341        return certificate_res[0].getPath().split('/')[-3]
342
[2078]343    def get_from_doc_faculty(self,doc,cached_data={}):
[1700]344        "return the students faculty"
345        if doc is None:
[1620]346            return None
[2078]347        if cached_data.has_key(doc.study_course):
348            return cached_data[doc.study_course]['faculty']
[1700]349        certificate_res = self.portal_catalog(id = doc.study_course)
350        if len(certificate_res) != 1:
351            return None
352        return certificate_res[0].getPath().split('/')[-4]
[1620]353
[2078]354    def get_from_doc_end_level(self,doc,cached_data={}):
[2069]355        "return the students end_level"
356        if doc is None:
357            return None
[2078]358        if cached_data.has_key(doc.study_course):
359            return cached_data[doc.study_course]['end_level']
[2069]360        certificate_res = self.portal_catalog(id = doc.study_course)
361        if len(certificate_res) != 1:
362            return None
363        return getattr(certificate_res[0].getObject().getContent(),'end_level','unknown')
364
[2078]365    def get_from_doc_level(self,doc,cached_data={}):
[1700]366        "return the students level"
367        if doc is None:
[1620]368            return None
[1700]369        return getattr(doc,'current_level',None)
[1620]370
[2078]371    def get_from_doc_mode(self,doc,cached_data={}):
[1705]372        "return the students mode"
[1700]373        if doc is None:
[1620]374            return None
[1705]375        cm = getattr(doc,'current_mode',None)
376        return cm
[1625]377
[1749]378
[2078]379    def get_from_doc_session(self,doc,cached_data={}):
[1705]380        "return the students current_session"
381        if doc is None:
382            return None
383        return getattr(doc,'current_session',None)
384
[2078]385    def get_from_doc_entry_session(self,doc,cached_data={}):
[1700]386        "return the students entry_session"
387        if doc is None:
[1620]388            return None
[1705]389        es = getattr(doc,'entry_session',None)
[1729]390        if es is not None and len(es) == 2:
[1705]391            return es
[1700]392        try:
393            digit = int(doc.jamb_reg_no[0])
394        except:
[1986]395            return "-1"
[1700]396        if digit < 8:
397            return "0%c" % doc.jamb_reg_no[0]
398        return "9%c" % doc.jamb_reg_no[0]
399
[2078]400    def get_from_doc_course(self,doc,cached_data={}):
[1620]401        "return the students study_course"
[1700]402        if doc is None:
[1620]403            return None
[1700]404        return getattr(doc,'study_course',None)
[1620]405
[2078]406    def get_from_doc_name(self,doc,cached_data={}):
[1620]407        "return the students name from the personal"
[1700]408        if doc is None:
[1620]409            return None
410        return "%s %s %s" % (doc.firstname,doc.middlename,doc.lastname)
411
[2078]412    def get_from_doc_verdict(self,doc,cached_data={}):
[1700]413        "return the students study_course"
414        if doc is None:
[1620]415            return None
[1700]416        return getattr(doc,'current_verdict',None)
[1702]417    ###)
[1620]418
[1702]419    def reindexIndex(self, name, REQUEST,pghandler=None): ###(
420        if isinstance(name, str):
421            name = (name,)
[1749]422        reindextypes = {}
[1702]423        reindex_special = []
424        for n in name:
425            if n in ("review_state","registered_courses"):
426                reindex_special.append(n)
427            else:
428                for pt in self.affected_types.keys():
[1707]429                    if n in self.affected_types[pt]['fields']:
[1702]430                        if reindextypes.has_key(pt):
431                            reindextypes[pt].append(n)
432                        else:
433                            reindextypes[pt]= [n]
434                        break
[2078]435        cached_data = {}
436        if set(name).intersection(set(('faculty','department','end_level'))):
437            cached_data = self.fill_certificates_dict()
[1702]438        students = self.portal_catalog(portal_type="Student")
[1954]439        if hasattr(self,'portal_catalog_real'):
440            aq_portal = self.portal_catalog_real.evalAdvancedQuery
441        else:
442            aq_portal = self.portal_catalog.evalAdvancedQuery
[1702]443        num_objects = len(students)
444        if pghandler:
445            pghandler.init('Refreshing catalog: %s' % self.absolute_url(1), num_objects)
446        noattr = set(('StudentClearance','StudentPersonal')) & set(reindextypes.keys())
[2084]447        #import pdb;pdb.set_trace()
[1702]448        for i in xrange(num_objects):
449            if pghandler: pghandler.report(i)
450            student_brain = students[i]
[1707]451            student_object = student_brain.getObject()
[2084]452            # query = Eq('path',student_brain.getPath())
453            # sub_brains_list = aq_portal(query)
454            # sub_brains = {}
455            # for sub_brain in sub_brains_list:
456            #     sub_brains[sub_brain.portal_type] = sub_brain
457            # student_path = student_brain.getPath()
[1702]458            data = {}
459            modified = False
460            sid = data['id'] = student_brain.getId
461            if reindex_special and 'review_state' in reindex_special:
462                modified = True
463                data['review_state'] = student_brain.review_state
[1707]464            sub_objects = False
465            for pt in reindextypes.keys():
[1702]466                modified = True
[1707]467                try:
468                    doc = getattr(student_object,self.affected_types[pt]['id']).getContent()
[2084]469                    #doc = sub_brains[pt].getObject().getContent()
470                    # path = "%s/%s" % (student_path,self.affected_types[pt]['id'])
471                    # doc = self.unrestrictedTraverse(path).getContent()
[1707]472                    sub_objects = True
473                except:
474                    continue
[2084]475                for field in set(name).intersection(self.affected_types[pt]['fields']):
[1707]476                    if hasattr(self,'get_from_doc_%s' % field):
[2078]477                        data[field] = getattr(self,'get_from_doc_%s' % field)(doc,
478                                                                              cached_data=cached_data)
[1707]479                    else:
480                        data[field] = getattr(doc,field)
481            if not sub_objects and noattr:
482                import_res = self.returning_import(id = sid)
483                if not import_res:
484                    continue
485                import_record = import_res[0]
486                data['matric_no'] = import_record.matric_no
487                data['sex'] = import_record.Sex == 'F'
488                data['name'] = "%s %s %s" % (import_record.Firstname,
489                                             import_record.Middlename,
490                                             import_record.Lastname)
[1815]491                data['jamb_reg_no'] = import_record.Entryregno
[1702]492            if reindex_special and 'registered_courses' in reindex_special:
[1954]493                try:
494                    study_course = getattr(student_object,"study_course")
495                    level_ids = study_course.objectIds()
496                except:
497                    continue
498                if not level_ids:
499                    continue
500                modified = True
501                level_ids.sort()
502                course_ids = getattr(study_course,level_ids[-1]).objectIds()
503                courses = []
504                for c in course_ids:
505                    if c.endswith('_co'):
506                        courses.append(c[:-3])
507                    else:
508                        courses.append(c)
509                data['registered_courses'] = courses
[1702]510            if modified:
511                self.modifyRecord(**data)
512        if pghandler: pghandler.finish()
513    ###)
[1620]514
515    def refreshCatalog(self, clear=0, pghandler=None): ###(
516        """ re-index everything we can find """
517        students_folder = self.portal_url.getPortalObject().campus.students
518        if clear:
[1724]519            self._catalog.clear()
[1700]520        students = self.portal_catalog(portal_type="Student")
521        num_objects = len(students)
[2078]522        cached_data = self.fill_certificates_dict()
[1620]523        if pghandler:
524            pghandler.init('Refreshing catalog: %s' % self.absolute_url(1), num_objects)
525        for i in xrange(num_objects):
526            if pghandler: pghandler.report(i)
[1700]527            student_brain = students[i]
528            spath = student_brain.getPath()
[1727]529            student_object = student_brain.getObject()
[1620]530            data = {}
[1700]531            sid = data['id'] = student_brain.getId
532            data['review_state'] = student_brain.review_state
[1707]533            sub_objects = False
534            for pt in self.affected_types.keys():
535                modified = True
536                try:
537                    doc = getattr(student_object,self.affected_types[pt]['id']).getContent()
538                    sub_objects = True
539                except:
[1727]540                    #from pdb import set_trace;set_trace()
[1707]541                    continue
542                for field in self.affected_types[pt]['fields']:
543                    if hasattr(self,'get_from_doc_%s' % field):
[2078]544                        data[field] = getattr(self,'get_from_doc_%s' % field)(doc,
545                                                                              cached_data=cached_data)
[1707]546                    else:
[1727]547                        data[field] = getattr(doc,field,None)
548            if not sub_objects:
[1700]549                import_res = self.returning_import(id = sid)
550                if not import_res:
[1620]551                    continue
[1700]552                import_record = import_res[0]
553                data['matric_no'] = import_record.matric_no
554                data['sex'] = import_record.Sex == 'F'
555                data['name'] = "%s %s %s" % (import_record.Firstname,
556                                             import_record.Middlename,
557                                             import_record.Lastname)
[1815]558                data['jamb_reg_no'] = import_record.Entryregno
[1727]559            else:
560                study_course = getattr(student_object,'study_course',None)
561                current_level = data.get('level',None)
562                data['registered_courses'] = []
563                if study_course and current_level and current_level in study_course.objectIds():
564                    level_obj = getattr(study_course,current_level)
[1749]565                    courses = []
[1727]566                    for c in level_obj.objectIds():
567                        if c.endswith('_co'):
568                            courses.append(c[:-3])
569                        else:
570                            courses.append(c)
[1749]571                    data['registered_courses'] = courses
[1700]572            self.addRecord(**data)
[1620]573        if pghandler: pghandler.finish()
574    ###)
575
[1700]576    security.declarePrivate('notify_event_listener') ###(
[1620]577    def notify_event_listener(self,event_type,object,infos):
578        "listen for events"
[1716]579        if not infos.has_key('rpath'):
580            return
[1702]581        pt = getattr(object,'portal_type',None)
582        mt = getattr(object,'meta_type',None)
[1954]583        students_catalog = self
[1702]584        data = {}
585        if pt == 'Student' and\
586           mt == 'CPS Proxy Folder' and\
587           event_type.startswith('workflow'):
588            data['id'] = object.getId()
589            data['review_state'] = self.portal_workflow.getInfoFor(object,'review_state',None)
590            students_catalog.modifyRecord(**data)
591            return
[1700]592        rpl = infos['rpath'].split('/')
[1731]593        if pt == 'Student' and mt == 'CPS Proxy Folder'\
594           and event_type == "sys_add_object":
[1700]595            student_id = object.id
596            try:
597                self.addRecord(id = student_id)
598            except ValueError:
599                pass
600            return
[1716]601        elif pt == 'StudentCourseResult' and mt == 'CPS Proxy Folder':
602            if event_type not in ("sys_add_object","sys_del_object"):
603                return
[2033]604            level_session = getattr(object.aq_parent.getContent(),'session','unknown')
605            if level_session not in (self.getSessionId()[-2:],'2006/2007'):
606                return
[1716]607            course_id = object.getId()
[1954]608            if course_id.endswith('_co'):
609                course_id = course_id[:-3]
[1716]610            student_id = object.absolute_url_path().split('/')[-4]
[1954]611            res = students_catalog(id = student_id)
[1716]612            if not res:
613                return
614            student_rec = res[0]
[2039]615            registered_courses = getattr(student_rec,'registered_courses',None)
616            if not registered_courses:
[1967]617                registered_courses = []
[2039]618            #import pdb;pdb.set_trace()
[1971]619            if event_type == "sys_add_object":
620                if course_id not in registered_courses:
621                    registered_courses.append(course_id)
622                else:
623                    return
[2039]624            elif registered_courses and event_type == "sys_del_object":
625                removed = False
[1954]626                while course_id in registered_courses:
[2039]627                    removed = True
[1954]628                    registered_courses.remove(course_id)
[2039]629                if not removed:
630                    return
[1716]631            data['id'] = student_id
632            data['registered_courses'] = registered_courses
[2069]633            self.modifyRecord(record = student_rec, **data)
[1971]634            return
[1716]635        if pt not in self.affected_types.keys():
[1700]636            return
[1716]637        if event_type not in ('sys_modify_object'):
638            return
[1700]639        if mt == 'CPS Proxy Folder':
640            return
[1716]641        for field in self.affected_types[pt]['fields']:
[1700]642            if hasattr(self,'get_from_doc_%s' % field):
643                data[field] = getattr(self,'get_from_doc_%s' % field)(object)
644            else:
645                data[field] = getattr(object,field)
646        data['id'] = rpl[2]
[1716]647        self.modifyRecord(**data)
[1700]648    ###)
[1620]649
[1625]650
[971]651InitializeClass(StudentsCatalog)
652
[1146]653###)
654
655class CoursesCatalog(WAeUPTable): ###(
[1716]656    security = ClassSecurityInfo()
[1146]657
658    meta_type = 'WAeUP Courses Catalog'
[2069]659    name = "courses_catalog"
[1146]660    key = "code"
661    def __init__(self):
662        WAeUPTable.__init__(self, 'courses_catalog')
663
[1716]664    def manage_catalogReindex(self, REQUEST, RESPONSE, URL1): ###(
665        """ clear the catalog, then re-index everything """
[1146]666
[1716]667        elapse = time.time()
668        c_elapse = time.clock()
669
670        pgthreshold = self._getProgressThreshold()
671        handler = (pgthreshold > 0) and ZLogHandler(pgthreshold) or None
672        self.refreshCatalog(clear=1, pghandler=handler)
673
674        elapse = time.time() - elapse
675        c_elapse = time.clock() - c_elapse
676
677        RESPONSE.redirect(
678            URL1 +
679            '/manage_catalogAdvanced?manage_tabs_message=' +
680            urllib.quote('Catalog Updated \n'
681                         'Total time: %s\n'
682                         'Total CPU time: %s' % (`elapse`, `c_elapse`)))
683    ###)
684
685    def reindexIndex(self, name, REQUEST,pghandler=None): ###(
686        if isinstance(name, str):
687            name = (name,)
688        courses = self.portal_catalog(portal_type="Course")
689        num_objects = len(courses)
690        if pghandler:
691            pghandler.init('Refreshing catalog: %s' % self.absolute_url(1), num_objects)
692        for i in xrange(num_objects):
693            if pghandler: pghandler.report(i)
694            course_brain = courses[i]
695            course_object = course_brain.getObject()
696            pl = course_brain.getPath().split('/')
697            data = {}
698            cid = data[self.key] = course_brain.getId
699            data['faculty'] = pl[-4]
700            data['department'] = pl[-3]
701            doc = course_object.getContent()
702            for field in name:
703                if field not in (self.key,'faculty','department'):
704                    data[field] = getattr(doc,field)
705            self.modifyRecord(**data)
706        if pghandler: pghandler.finish()
707    ###)
708
709    def refreshCatalog(self, clear=0, pghandler=None): ###(
710        """ re-index everything we can find """
[1724]711        if clear:
712            self._catalog.clear()
[1716]713        courses = self.portal_catalog(portal_type="Course")
714        num_objects = len(courses)
715        if pghandler:
716            pghandler.init('Refreshing catalog: %s' % self.absolute_url(1), num_objects)
[1724]717        #from pdb import set_trace;set_trace()
[1716]718        for i in xrange(num_objects):
719            if pghandler: pghandler.report(i)
720            course_brain = courses[i]
[1724]721            course_doc = course_brain.getObject().getContent()
[1716]722            pl = course_brain.getPath().split('/')
723            data = {}
[1724]724            for field in self.schema():
[1749]725                data[field] = getattr(course_doc,field,None)
[1716]726            data[self.key] = course_brain.getId
[1724]727            ai = pl.index('academics')
728            data['faculty'] = pl[ai +1]
729            data['department'] = pl[ai +2]
730            if clear:
731                self.addRecord(**data)
732            else:
733                self.modifyRecord(**data)
[1716]734        if pghandler: pghandler.finish()
735    ###)
736
737    security.declarePrivate('notify_event_listener') ###(
738    def notify_event_listener(self,event_type,object,infos):
739        "listen for events"
740        if not infos.has_key('rpath'):
741            return
742        pt = getattr(object,'portal_type',None)
743        mt = getattr(object,'meta_type',None)
744        if pt != 'Course':
745            return
746        data = {}
747        rpl = infos['rpath'].split('/')
748        if event_type not in ("sys_add_object","sys_modify_object","sys_del_object"):
749            return
750        course_id = object.getId()
751        data[self.key] = course_id
[1724]752        if event_type == "sys_add_object" and mt == 'CPS Proxy Folder':
[1716]753            try:
754                self.addRecord(**data)
755            except ValueError:
[1724]756                return
757            course_id = object.getId()
758            doc = object.getContent()
759            if doc is None:
760                return
761            for field in self.schema():
[1749]762                data[field] = getattr(doc,field,None)
[1724]763            data[self.key] = course_id
764            ai = rpl.index('academics')
765            data['faculty'] = rpl[ai +1]
766            data['department'] = rpl[ai +2]
767            self.modifyRecord(**data)
768            return
[1716]769        if event_type == "sys_del_object":
770            self.deleteRecord(course_id)
[1724]771            return
[1716]772        if event_type == "sys_modify_object" and mt == 'Course':
[1724]773            #from pdb import set_trace;set_trace()
[1716]774            for field in self.schema():
[1749]775                data[field] = getattr(object,field,None)
[1716]776            course_id = object.aq_parent.getId()
777            data[self.key] = course_id
[1724]778            ai = rpl.index('academics')
779            data['faculty'] = rpl[ai +1]
780            data['department'] = rpl[ai +2]
[1716]781            self.modifyRecord(**data)
782    ###)
783
784
[1146]785InitializeClass(CoursesCatalog)
[1151]786###)
[1146]787
[2084]788class CourseResults(WAeUPTable): ###(
[2069]789    security = ClassSecurityInfo()
790
791    meta_type = 'WAeUP Results Catalog'
792    name = "course_results"
[2084]793    key = "key" #student_id + level + course_id
[2069]794    def __init__(self):
795        WAeUPTable.__init__(self, 'course_results')
[2084]796        self._queue = []
797       
798    def addRecord(self, **data): ###(
799        # The uid is the same as "bed".
800        uid = key = "%(student_id)s|%(level_id)s|%(course_id)s" % data
801        if key in self._queue:
802            return uid
803        data['queue_status'] = ADDING_SHEDULED
804        data['%s' % self.key] = uid
805        res = self.searchResults({"%s" % self.key : uid})
806        if len(res) > 0:
807            raise ValueError("More than one record with uid %s" % uid)
808        self.catalog_object(dict2ob(data), uid=uid)
809        if not hasattr(self,'_queue'):
810            self._queue = []
811        self._queue.append(key)
812        self._p_changed = 1
813        return uid
814    ###)
[2069]815
[2084]816    def deleteRecord(self, uid): ###(
817        self.uncatalog_object(uid)
818        if uid in self._queue:
819            self._queue.remove(uid)
820    ###)
821
822    def getCourses(self,student_id,level_id): ###(
823        query = Eq('student_id',student_id) & Eq('level_id', level_id)
824        carry_overs = []
825        normal = []
826        credits = 0
827        for brain in self.course_results.evalAdvancedQuery(query):
828            d = {}
829            credits += int(brain.credits)
830            for field in self.schema():
831                d[field] = getattr(brain,field,'')
832            d['sheduled'] = brain.queue_status == ADDING_SHEDULED
833            d['coe'] = 'Elective'
834            if brain.core_or_elective:
835                d['coe'] = 'Core'
836            d['title'] = self.courses_catalog.evalAdvancedQuery(Eq('code',brain.code))[0].title
837            if brain.code.endswith('_co'):
838                carry_overs.append(d)
839            else:
840                normal.append(d)
841        normal.sort(cmp=lambda x,y: cmp(x['semester'], y['semester']))
842        carry_overs.sort(cmp=lambda x,y: cmp(x['semester'], y['semester']))
843        return credits,carry_overs,normal
844    ###)
845
846    def addObject(self,record): ###(
847        key = record.key
848        student_id,level_id,course_id = key.split('|')
849        level = getattr(getattr(self.portal_url.getPortalObject().campus.students,student_id).study_course,level_id)
850        cr_id = level.invokeFactory('StudentCourseResult', course_id)
851        course_result = getattr(level,cr_id)
852        self.portal_workflow.doActionFor(course_result,'open')
853        d = {}
854        for field in self.schema():
855            d[field] = getattr(record,field,'')
856        course_result.getContent().edit(mapping=d)
857    ###)
858       
859    security.declareProtected(ModifyPortalContent,"process_queue") ###(
860    def process_queue(self,limit=None):
861        """adds objects and removes them from the queue.
862        If limit is specified, at most (limit) events are removed.
863        """
864        if not hasattr(self,'_queue'):
865            return 0
866        queue= self._queue
867        if not limit or len(queue) <= limit:
868            keys = self._queue[:]
869        else:
870            keys = queue[:limit]
871        if not keys:
872            records = self.evalAdvancedQuery(Eq('queue_status',ADDING_SHEDULED))
873        else:
874            records = self.evalAdvancedQuery(In("%s" % self.key,keys))
875        for record in records:
876            if record.queue_status == OBJECT_CREATED:
877                continue
878            self.addObject(record)
879            data = {}
880            data['key'] = record.key
881            data['queue_status'] = OBJECT_CREATED
882            self.modifyRecord(**data)
883        count = 0
884        for key in keys:
885            count +=1
886            if key in self._queue:
887                self._queue.remove(key)
888        self._p_changed = 1
889        return count,len(self._queue)
890    ###)
891
892    def manage_catalogClear(self, REQUEST=None, RESPONSE=None, URL1=None): ###(
893        """ clears the whole enchilada """
894        self._catalog.clear()
895
896        if REQUEST and RESPONSE:
897            RESPONSE.redirect(
898              URL1 +
899              '/manage_catalogAdvanced?manage_tabs_message=Catalog%20Cleared')
900    ###)
901
[2069]902    def manage_catalogReindex(self, REQUEST, RESPONSE, URL1): ###(
903        """ clear the catalog, then re-index everything """
904
905        elapse = time.time()
906        c_elapse = time.clock()
907
908        pgthreshold = self._getProgressThreshold()
909        handler = (pgthreshold > 0) and ZLogHandler(pgthreshold) or None
[2084]910        self.refreshCatalog(clear=1, pghandler=handler)
[2069]911
912        elapse = time.time() - elapse
913        c_elapse = time.clock() - c_elapse
914
915        RESPONSE.redirect(
916            URL1 +
917            '/manage_catalogAdvanced?manage_tabs_message=' +
918            urllib.quote('Catalog Updated \n'
919                         'Total time: %s\n'
920                         'Total CPU time: %s' % (`elapse`, `c_elapse`)))
921    ###)
922
[2084]923    def refreshCatalog(self, clear=1, pghandler=None): ###(
924        """ re-index everything we can find """
925        students_folder = self.portal_url.getPortalObject().campus.students
926        if clear:
927            self._catalog.clear()
928        course_results = self.portal_catalog(portal_type="StudentCourseResult")
929        num_objects = len(course_results)
930        if pghandler:
931            pghandler.init('Refreshing catalog: %s' % self.absolute_url(1), num_objects)
932        #import pdb;pdb.set_trace()
933        for i in xrange(num_objects):
934            if pghandler:
935                pghandler.report(i)
936            course_result_brain = course_results[i]
937            path_list = course_result_brain.getPath().split('/')
938            course_result_object = course_result_brain.getObject()
939            course_result_doc = course_result_object.getContent()
940            data = {}
941            level_id = path_list[-2]
942            course_id = path_list[-1]
943            student_id = path_list[-4]
944            for field in self.schema():
945                data[field] = getattr(course_result_doc,field,'')
946            data['key'] = key = "%(student_id)s|%(level_id)s|%(course_id)s" % vars()
947            data['student_id'] = student_id
948            data['level_id'] = level_id
949            data['queue_status'] = OBJECT_CREATED
950            self.catalog_object(dict2ob(data), uid=key)
951        if pghandler: pghandler.finish()
952    ###)
[2069]953
[2084]954    security.declarePrivate('notify_event_listener') ###(
955    def notify_event_listener(self,event_type,object,infos):
956        "listen for events"
957        if not infos.has_key('rpath'):
958            return
959        pt = getattr(object,'portal_type',None)
960        mt = getattr(object,'meta_type',None)
961        data = {}
962        rpl = infos['rpath'].split('/')
963        if mt == 'CPS Proxy Folder':
964            return
965        if pt == 'StudentCourseResult' and event_type == "sys_modify_object":
966            data["%s" % self.key] = uid = "%s|%s|%s" % (rpl[-5],rpl[-3],rpl[-2])
967            records = self.searchResults({"%s" % self.key : uid})
968            if len(records) > 1:
969                # Can not happen, but anyway...
970                raise ValueError("More than one record with uid %s" % uid)
971            if len(records) == 0:
972                raise KeyError("No record for uid %s" % uid)
973            record = records[0]
974            #import pdb;pdb.set_trace()
975            for field in ('core_or_elective','score'):
976                value = getattr(object,field,None)
977                data[field] = value
978            self.modifyRecord(record,**data)
979    ###)
980
981InitializeClass(CourseResults)
[2069]982###)
983
[1625]984class OnlinePaymentsImport(WAeUPTable): ###(
[1620]985
986    meta_type = 'WAeUP Online Payment Transactions'
[1625]987    name = "online_payments_import"
[1620]988    key = "order_id"
989    def __init__(self):
990        WAeUPTable.__init__(self, self.name)
991
992
[2069]993InitializeClass(OnlinePaymentsImport)
[1620]994###)
995
[1151]996class ReturningImport(WAeUPTable): ###(
[1146]997
[1151]998    meta_type = 'Returning Import Table'
999    name = "returning_import"
[1146]1000    key = "matric_no"
1001    def __init__(self):
[1151]1002        WAeUPTable.__init__(self, 'returning_import')
[1146]1003
1004
[1151]1005InitializeClass(ReturningImport)
1006###)
[1146]1007
1008class ResultsImport(WAeUPTable): ###(
1009
1010    meta_type = 'Results Import Table'
1011    name = "results_import"
1012    key = "key"
1013    def __init__(self):
1014        WAeUPTable.__init__(self, 'results_import')
1015
1016
1017InitializeClass(ResultsImport)
1018
1019###)
1020
1021class PaymentsCatalog(WAeUPTable): ###(
1022
1023    meta_type = 'WAeUP Payments Catalog'
1024    name = "students_catalog"
1025    key = "id"
1026    def __init__(self):
1027        WAeUPTable.__init__(self, 'payments_catalog')
1028
1029
1030InitializeClass(PaymentsCatalog)
1031
1032###)
1033
[414]1034# BBB:
1035AccomodationTable = AccommodationTable
Note: See TracBrowser for help on using the repository browser.