source: WAeUP_SRP/trunk/WAeUPTables.py @ 2181

Last change on this file since 2181 was 2113, checked in by Henrik Bettermann, 17 years ago

select widgets for courses

  • Property svn:keywords set to Id
File size: 50.4 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 2113 2007-08-17 12:37:42Z henrik $
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
[2094]27from Products.CMFCore.utils import getToolByName
28from Products.CMFCore.CatalogTool import CatalogTool
29from Products.CPSSchemas.StorageAdapter import MappingStorageAdapter
30from Products.CPSSchemas.DataStructure import DataStructure
31from Products.CPSSchemas.DataModel import DataModel
32from Products.AdvancedQuery import Eq, Between, Le,In
[1700]33import urllib
[1620]34import DateTime,time
[780]35import csv,re
36import logging
37import Globals
38p_home = Globals.package_home(globals())
39i_home = Globals.INSTANCE_HOME
40
[2084]41ADDING_SHEDULED = "adding_sheduled"
42OBJECT_CREATED = "object_created"
43
[363]44from interfaces import IWAeUPTable
45
46class AttributeHolder(object):
47    pass
48
49def dict2ob(dict):
50    ob = AttributeHolder()
51    for key, value in dict.items():
52        setattr(ob, key, value)
53    return ob
54
[1146]55class WAeUPTable(ZCatalog): ###(
[834]56
[363]57    implements(IWAeUPTable)
[780]58    security = ClassSecurityInfo()
[2094]59    meta_type = None
[2099]60
[2094]61    def __init__(self,name=None):
62        if name ==  None:
63            name = self.name
64        ZCatalog.__init__(self,name)
[2099]65
[2094]66    def refreshCatalog(self, clear=0, pghandler=None): ###(
[1620]67        """ don't refresh for a normal table """
68
69        if self.REQUEST and self.REQUEST.RESPONSE:
70            self.REQUEST.RESPONSE.redirect(
71              URL1 +
72              '/manage_catalogAdvanced?manage_tabs_message=Catalog%20refresh%20not%20implemented')
73
[2094]74###)
75
76    def manage_catalogClear(self, REQUEST=None, RESPONSE=None, URL1=None): ###(
[1620]77        """ clears the whole enchilada """
[1986]78
[1916]79        #if REQUEST and RESPONSE:
80        #    RESPONSE.redirect(
81        #      URL1 +
82        #      '/manage_catalogAdvanced?manage_tabs_message=Catalog%20Clearing%20disabled')
[1620]83
[1916]84        self._catalog.clear()
[1620]85        if REQUEST and RESPONSE:
86            RESPONSE.redirect(
87              URL1 +
[1916]88              '/manage_catalogAdvanced?manage_tabs_message=Catalog%20cleared')
[1620]89
[2094]90###)
91
92    def addRecord(self, **data): ###(
[502]93        # The uid is the same as "bed".
94        uid = data[self.key]
95        res = self.searchResults({"%s" % self.key : uid})
96        if len(res) > 0:
97            raise ValueError("More than one record with uid %s" % uid)
98        self.catalog_object(dict2ob(data), uid=uid)
99        return uid
[834]100
[2094]101###)
102
[363]103    def deleteRecord(self, uid):
104        self.uncatalog_object(uid)
[834]105
[502]106    def searchAndSetRecord(self, **data):
107        raise NotImplemented
108
[2094]109    def modifyRecord(self, record=None, **data): ###(
[502]110        #records = self.searchResults(uid=uid)
111        uid = data[self.key]
[2069]112        if record is None:
113            records = self.searchResults({"%s" % self.key : uid})
114            if len(records) > 1:
115                # Can not happen, but anyway...
116                raise ValueError("More than one record with uid %s" % uid)
117            if len(records) == 0:
118                raise KeyError("No record for uid %s" % uid)
119            record = records[0]
[363]120        record_data = {}
121        for field in self.schema() + self.indexes():
122            record_data[field] = getattr(record, field)
123        # Add the updated data:
124        record_data.update(data)
125        self.catalog_object(dict2ob(record_data), uid)
126
[2094]127###)
128
129    def reindexIndex(self, name, REQUEST,pghandler=None): ###(
[1062]130        if isinstance(name, str):
[2094]131            name =  (name,)
[1062]132        paths = self._catalog.uids.items()
133        i = 0
134        #import pdb;pdb.set_trace()
135        for p,rid in paths:
136            i += 1
137            metadata = self.getMetadataForRID(rid)
138            record_data = {}
139            for field in name:
140                record_data[field] = metadata.get(field)
141            uid = metadata.get(self.key)
142            self.catalog_object(dict2ob(record_data), uid, idxs=name,
143                                update_metadata=0)
[1082]144
[2094]145###)
146
147    security.declareProtected(ModifyPortalContent,"exportAllRecords") ###(
[780]148    def exportAllRecords(self):
149        "export a WAeUPTable"
150        #import pdb;pdb.set_trace()
151        fields = [field for field in self.schema()]
152        format = ','.join(['"%%(%s)s"' % fn for fn in fields])
153        csv = []
154        csv.append(','.join(['"%s"' % fn for fn in fields]))
155        for uid in self._catalog.uids:
156            records = self.searchResults({"%s" % self.key : uid})
157            if len(records) > 1:
158                # Can not happen, but anyway...
159                raise ValueError("More than one record with uid %s" % uid)
160            if len(records) == 0:
161                raise KeyError("No record for uid %s" % uid)
162            rec = records[0]
163            csv.append(format % rec)
164        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
165        open("%s/import/%s-%s.csv" % (i_home,self.getId(),current),"w+").write('\n'.join(csv))
[2094]166
167###)
168
169    security.declarePrivate("_import") ###(
170    def _import(self,filename,schema,layout, mode,logger):
171        "import data from csv"
172        import transaction
173        import random
174        pm = self.portal_membership
175        member = pm.getAuthenticatedMember()
176        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
177        import_fn = "%s/import/%s.csv" % (i_home,filename)
178        imported_fn = "%s/import/%s_imported%s.csv" % (i_home,filename,current)
179        not_imported_fn = "%s/import/%s_not_imported%s.csv" % (i_home,filename,current)
180        start = True
181        tr_count = 1
182        total_imported = 0
183        total_not_imported = 0
184        total = 0
185        iname =  "%s" % filename
[2112]186        not_imported = []
187        imported = []
188        valid_records = []
189        invalid_records = []
190        d = {}
191        d['mode'] = mode
192        d['imported'] = total_imported
193        d['not_imported'] = total_not_imported
194        d['valid_records'] = valid_records
195        d['invalid_records'] = invalid_records
196        d['import_fn'] = import_fn
197        d['imported_fn'] = imported_fn
198        d['not_imported_fn'] = not_imported_fn
[2094]199        if schema is None:
200            em = 'No schema specified'
201            logger.error(em)
[2112]202            return d
[2094]203        if layout is None:
204            em = 'No layout specified'
205            logger.error(em)
[2112]206            return d
[2094]207        validators = {}
208        for widget in layout.keys():
[2112]209            try:
210                validators[widget] = layout[widget].validate
211            except AttributeError:
212                logger.info('%s has no validate attribute' % widget)
213                return d
[2094]214        # if mode == 'edit':
215        #     importer = self.importEdit
216        # elif mode == 'add':
217        #     importer = self.importAdd
218        # else:
219        #     importer = None
220        try:
221            items = csv.DictReader(open(import_fn,"rb"))
222        except:
223            em = 'Error reading %s.csv' % filename
224            logger.error(em)
225            return d
226        for item in items:
227            if start:
228                start = False
229                logger.info('%s starts import from %s.csv' % (member,filename))
230                #import_keys = [k for k in item.keys() if not k.startswith('ignore')]
231                attrs = csv.reader(open("%s/import/%s.csv" % (i_home,filename),"rb")).next()
232                import_keys = [k for k in attrs if not (k.startswith('ignore') or k.isupper())]
233                diff2schema = set(import_keys).difference(set(schema.keys()))
234                diff2layout = set(import_keys).difference(set(layout.keys()))
235                if diff2layout:
236                    em = "not ignorable key(s) %s found in heading" % diff2layout
237                    logger.info(em)
238                    return d
239                s = ','.join(['"%s"' % fn for fn in import_keys])
240                open(not_imported_fn,"a").write(s + ',"Error"'+ '\n')
241                #s = '"id",' + s
242                open(imported_fn,"a").write(s + '\n')
243                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
244                format_error = format + ',"%(Error)s"'
245                #format = '"%(id)s",'+ format
246                adapters = [MappingStorageAdapter(schema, item)]
247            dm = DataModel(item, adapters,context=self)
248            ds = DataStructure(data=item,datamodel=dm)
249            error_string = ""
250            for k in import_keys:
251                if not validators[k](ds,mode=mode):
252                    error_string += " %s : %s" % (k,ds.getError(k))
253            # if not error_string and importer:
254            #     item.update(dm)
255            #     item['id'],error = importer(item)
256            #     if error:
257            #         error_string += error
258            if error_string:
259                item['Error'] = error_string
260                invalid_records.append(dm)
261                not_imported.append(format_error % item)
262                total_not_imported += 1
263            else:
264                em = format % item
265                valid_records.append(dm)
266                imported.append(em)
267                #logger.info("%(total_imported)d of %(total)d %(em)s" % vars())
268                tr_count += 1
269                total_imported += 1
270            total += 1
271            # if importer and total_imported and not total_imported % 1000:
272            #     transaction.commit()
273            #     if len(not_imported) > 0:
274            #         open(not_imported_fn,"a").write('\n'.join(not_imported) + '\n')
275            #         not_imported = []
276            #     if len(imported) > 0:
277            #         open(imported_fn,"a").write('\n'.join(imported) + '\n')
278            #         imported = []
279            #     em = '%d transactions committed\n' % (tr_count)
280            #     regs = []
281            #     logger.info(em)
282            #     tr_count = 0
283        if len(imported) > 0:
284            open(imported_fn,"a").write('\n'.join(imported))
285        if len(not_imported) > 0:
286            open(not_imported_fn,"a").write('\n'.join(not_imported))
287        #em = "Imported: %d, not imported: %d of total %d" % (total_imported,total_not_imported,total)
288        d['imported'] = total_imported
289        d['not_imported'] = total_not_imported
290        d['valid_records'] = valid_records
291        d['invalid_records'] = invalid_records
292        d['imported_fn'] = imported_fn
293        d['not_imported_fn'] = not_imported_fn
294        #logger.info(em)
295        return d
[1935]296    ###)
[2094]297###)
[834]298
[1146]299class AccommodationTable(WAeUPTable): ###(
[834]300
[404]301    meta_type = 'WAeUP Accommodation Tool'
[2094]302    name = "portal_accommodation"
[502]303    key = "bed"
[2094]304    def __init__(self,name=None):
305        if name ==  None:
306            name = self.name
307        WAeUPTable.__init__(self, name)
[363]308
[635]309    def searchAndReserveBed(self, student_id,bed_type):
310        records = self.searchResults({'student' : student_id})
311        if len(records) > 0:
[1293]312            return -1,"Student with Id %s already booked bed %s." % (student_id,records[0].bed)
[834]313
[673]314        records = [r for r in self.searchResults({'bed_type' : bed_type}) if not r.student]
[686]315        #import pdb;pdb.set_trace()
[635]316        if len(records) == 0:
[1306]317            return -2,"No bed available"
[635]318        rec = records[0]
319        self.modifyRecord(bed=rec.bed,student=student_id)
[1571]320        s_logger = logging.getLogger('WAeUPTables.AccommodationTable.searchAndReserveBed')
321        s_logger.info('%s reserved bed %s' % (student_id,rec.bed))
[635]322        return 1,rec.bed
[363]323
[834]324
[404]325InitializeClass(AccommodationTable)
[411]326
[1146]327###)
328
329class PinTable(WAeUPTable): ###(
[1030]330    from ZODB.POSException import ConflictError
[440]331    meta_type = 'WAeUP Pin Tool'
[2094]332    name = "portal_pins"
[502]333    key = 'pin'
[2094]334    def __init__(self,name=None):
335        if name ==  None:
336            name = self.name
337        WAeUPTable.__init__(self, name)
[1082]338
339
[710]340    def searchAndSetRecord(self, uid, student_id,prefix):
[502]341        #records = self.searchResults(uid=uid)
[710]342        records = self.searchResults(student = student_id)
[990]343        #import pdb;pdb.set_trace()
[1776]344        if len(records) > 0 and prefix in ('CLR','APP'):
[710]345            for r in records:
[834]346                if r.pin != uid and r.prefix_batch.startswith(prefix):
[710]347                    return -2
[502]348        records = self.searchResults({"%s" % self.key : uid})
349        if len(records) > 1:
350            # Can not happen, but anyway...
351            raise ValueError("More than one record with uid %s" % uid)
352        if len(records) == 0:
353            return -1
354        record = records[0]
355        if record.student == "":
356            record_data = {}
357            for field in self.schema() + self.indexes():
358                record_data[field] = getattr(record, field)
359            # Add the updated data:
[635]360            record_data['student'] = student_id
[1030]361            try:
362                self.catalog_object(dict2ob(record_data), uid)
363                return 1
364            except ConflictError:
365                return 2
[990]366        if record.student.upper() != student_id.upper():
[502]367            return 0
[997]368        if record.student.upper() == student_id.upper():
[502]369            return 2
[997]370        return -3
[440]371
372InitializeClass(PinTable)
373
[1146]374###)
[966]375
[1146]376class PumeResultsTable(WAeUPTable): ###(
377
[966]378    meta_type = 'WAeUP PumeResults Tool'
[2094]379    name = "portal_pumeresults"
[966]380    key = "jamb_reg_no"
[2094]381    def __init__(self,name=None):
382        if name ==  None:
383            name = self.name
384        WAeUPTable.__init__(self, name)
[966]385
386
387InitializeClass(PumeResultsTable)
388
[1146]389###)
[971]390
[2094]391class ApplicantsCatalog(WAeUPTable): ###(
392
[2113]393    meta_type = 'WAeUP Applicants Catalog'
[2094]394    name = "applicants_catalog"
395    key = "reg_no"
396    security = ClassSecurityInfo()
[2099]397
[2094]398    def __init__(self,name=None):
399        if name ==  None:
400            name = self.name
401        WAeUPTable.__init__(self, name)
402
403    security.declareProtected(ModifyPortalContent,"importCSV")###(
404    def importCSV(self,filename="JAMB_data",
405                  schema_id="application",
406                  layout_id="application",
407                  mode='add'):
408        """ import JAMB data """
409        stool = getToolByName(self, 'portal_schemas')
410        ltool = getToolByName(self, 'portal_layouts')
411        schema = stool._getOb(schema_id)
412        if schema is None:
413            em = 'No such schema %s' % schema_id
414            logger.error(em)
415            return
416        layout = ltool._getOb(layout_id)
417        if layout is None:
418            em = 'No such layout %s' % layout_id
419            logger.error(em)
420            return
[2099]421        logger = logging.getLogger('WAeUPTables.ApplicantsCatalog.importCSV')
[2094]422        d = self._import(filename,schema,layout,mode,logger)
423        if len(d['valid_records']) > 0:
424            for record in d['valid_records']:
425                #import pdb;pdb.set_trace()
426                if mode == "add":
427                    self.addRecord(**dict(record.items()))
428                    logger.info("added %s" % record.items())
429                elif mode == "edit":
430                    self.modifyRecord(**dict(record.items()))
431                    logger.info("edited %s" % record.items())
432                else:
433                    logger.info("invalid mode: %s" % mode)
434        logger.info("%(mode)sed %(imported)d records, invalid written to %(not_imported_fn)s" % d)
435###)
436
437InitializeClass(ApplicantsCatalog)
438
439###)
440
[1146]441class StudentsCatalog(WAeUPTable): ###(
[1620]442    security = ClassSecurityInfo()
[1146]443
[971]444    meta_type = 'WAeUP Students Catalog'
445    name = "students_catalog"
446    key = "id"
[1700]447    affected_types = {   ###(
[1749]448                      'StudentApplication':
[2069]449                      {'id': 'application',
450                       'fields':
451                       ('jamb_reg_no',
452                        'entry_mode',
453                        #'entry_level',
454                        'entry_session',
455                       )
456                      },
[1700]457                      'StudentClearance':
[2069]458                      {'id': 'clearance',
459                       'fields':
460                       ('matric_no',
461                        'lga',
462                       )
463                      },
464                      'StudentPersonal':
465                      {'id': 'personal',
466                       'fields':
467                       ('name',
468                        'sex',
469                        'perm_address',
470                        'email',
471                        'phone',
472                       )
473                      },
474                      'StudentStudyCourse':
475                      {'id': 'study_course',
476                       'fields':
477                       ('course', # study_course
478                        'faculty', # from certificate
479                        'department', # from certificate
480                        'end_level', # from certificate
481                        'level', # current_level
482                        'mode',  # current_mode
483                        'session', # current_session
484                        'verdict', # current_verdict
485                       )
486                      },
487                     }
[1700]488    ###)
[1625]489
[2094]490    def __init__(self,name=None):
491        if name ==  None:
492            name = self.name
493        WAeUPTable.__init__(self, name)
[1620]494        return
[1625]495
[1700]496    def manage_catalogClear(self, REQUEST=None, RESPONSE=None, URL1=None):
497        """ clears the whole enchilada """
498        self._catalog.clear()
[971]499
[1700]500        if REQUEST and RESPONSE:
501            RESPONSE.redirect(
502              URL1 +
503              '/manage_catalogAdvanced?manage_tabs_message=Catalog%20Cleared')
[971]504
[1700]505    def manage_catalogReindex(self, REQUEST, RESPONSE, URL1): ###(
506        """ clear the catalog, then re-index everything """
507
508        elapse = time.time()
509        c_elapse = time.clock()
510
511        pgthreshold = self._getProgressThreshold()
512        handler = (pgthreshold > 0) and ZLogHandler(pgthreshold) or None
513        self.refreshCatalog(clear=1, pghandler=handler)
514
515        elapse = time.time() - elapse
516        c_elapse = time.clock() - c_elapse
517
518        RESPONSE.redirect(
519            URL1 +
520            '/manage_catalogAdvanced?manage_tabs_message=' +
521            urllib.quote('Catalog Updated \n'
522                         'Total time: %s\n'
523                         'Total CPU time: %s' % (`elapse`, `c_elapse`)))
524    ###)
525
[2084]526    def fill_certificates_dict(self): ###(
[2078]527        "return certificate data in  dict"
528        certificates_brains = self.portal_catalog(portal_type ='Certificate')
529        d = {}
530        for cb in certificates_brains:
531            certificate_doc = cb.getObject().getContent()
532            cb_path = cb.getPath().split('/')
533            ld = {}
534            ld['faculty'] = cb_path[-4]
535            ld['department'] = cb_path[-3]
536            ld['end_level'] = getattr(certificate_doc,'end_level','999')
537            d[cb.getId] = ld
538        return d
[2084]539    ###)
540
[2078]541    def get_from_doc_department(self,doc,cached_data={}): ###(
[1620]542        "return the students department"
[1700]543        if doc is None:
[1620]544            return None
[2078]545        if cached_data.has_key(doc.study_course):
546            return cached_data[doc.study_course]['department']
[1700]547        certificate_res = self.portal_catalog(id = doc.study_course)
[1620]548        if len(certificate_res) != 1:
549            return None
550        return certificate_res[0].getPath().split('/')[-3]
551
[2078]552    def get_from_doc_faculty(self,doc,cached_data={}):
[1700]553        "return the students faculty"
554        if doc is None:
[1620]555            return None
[2078]556        if cached_data.has_key(doc.study_course):
557            return cached_data[doc.study_course]['faculty']
[1700]558        certificate_res = self.portal_catalog(id = doc.study_course)
559        if len(certificate_res) != 1:
560            return None
561        return certificate_res[0].getPath().split('/')[-4]
[1620]562
[2099]563    def get_from_doc_end_level(self,doc,cached_data={}):
[2069]564        "return the students end_level"
565        if doc is None:
566            return None
[2078]567        if cached_data.has_key(doc.study_course):
568            return cached_data[doc.study_course]['end_level']
[2069]569        certificate_res = self.portal_catalog(id = doc.study_course)
570        if len(certificate_res) != 1:
571            return None
572        return getattr(certificate_res[0].getObject().getContent(),'end_level','unknown')
573
[2078]574    def get_from_doc_level(self,doc,cached_data={}):
[1700]575        "return the students level"
576        if doc is None:
[1620]577            return None
[1700]578        return getattr(doc,'current_level',None)
[1620]579
[2078]580    def get_from_doc_mode(self,doc,cached_data={}):
[1705]581        "return the students mode"
[1700]582        if doc is None:
[1620]583            return None
[1705]584        cm = getattr(doc,'current_mode',None)
585        return cm
[1625]586
[1749]587
[2078]588    def get_from_doc_session(self,doc,cached_data={}):
[1705]589        "return the students current_session"
590        if doc is None:
591            return None
592        return getattr(doc,'current_session',None)
593
[2078]594    def get_from_doc_entry_session(self,doc,cached_data={}):
[1700]595        "return the students entry_session"
596        if doc is None:
[1620]597            return None
[1705]598        es = getattr(doc,'entry_session',None)
[1729]599        if es is not None and len(es) == 2:
[1705]600            return es
[1700]601        try:
602            digit = int(doc.jamb_reg_no[0])
603        except:
[1986]604            return "-1"
[1700]605        if digit < 8:
606            return "0%c" % doc.jamb_reg_no[0]
607        return "9%c" % doc.jamb_reg_no[0]
608
[2078]609    def get_from_doc_course(self,doc,cached_data={}):
[1620]610        "return the students study_course"
[1700]611        if doc is None:
[1620]612            return None
[1700]613        return getattr(doc,'study_course',None)
[1620]614
[2078]615    def get_from_doc_name(self,doc,cached_data={}):
[1620]616        "return the students name from the personal"
[1700]617        if doc is None:
[1620]618            return None
619        return "%s %s %s" % (doc.firstname,doc.middlename,doc.lastname)
620
[2078]621    def get_from_doc_verdict(self,doc,cached_data={}):
[1700]622        "return the students study_course"
623        if doc is None:
[1620]624            return None
[1700]625        return getattr(doc,'current_verdict',None)
[1702]626    ###)
[1620]627
[1702]628    def reindexIndex(self, name, REQUEST,pghandler=None): ###(
629        if isinstance(name, str):
630            name = (name,)
[1749]631        reindextypes = {}
[1702]632        reindex_special = []
633        for n in name:
634            if n in ("review_state","registered_courses"):
635                reindex_special.append(n)
636            else:
637                for pt in self.affected_types.keys():
[1707]638                    if n in self.affected_types[pt]['fields']:
[1702]639                        if reindextypes.has_key(pt):
640                            reindextypes[pt].append(n)
641                        else:
642                            reindextypes[pt]= [n]
643                        break
[2078]644        cached_data = {}
645        if set(name).intersection(set(('faculty','department','end_level'))):
646            cached_data = self.fill_certificates_dict()
[1702]647        students = self.portal_catalog(portal_type="Student")
[1954]648        if hasattr(self,'portal_catalog_real'):
649            aq_portal = self.portal_catalog_real.evalAdvancedQuery
650        else:
651            aq_portal = self.portal_catalog.evalAdvancedQuery
[1702]652        num_objects = len(students)
653        if pghandler:
654            pghandler.init('Refreshing catalog: %s' % self.absolute_url(1), num_objects)
655        noattr = set(('StudentClearance','StudentPersonal')) & set(reindextypes.keys())
[2084]656        #import pdb;pdb.set_trace()
[1702]657        for i in xrange(num_objects):
658            if pghandler: pghandler.report(i)
659            student_brain = students[i]
[1707]660            student_object = student_brain.getObject()
[2084]661            # query = Eq('path',student_brain.getPath())
662            # sub_brains_list = aq_portal(query)
663            # sub_brains = {}
664            # for sub_brain in sub_brains_list:
665            #     sub_brains[sub_brain.portal_type] = sub_brain
666            # student_path = student_brain.getPath()
[1702]667            data = {}
668            modified = False
669            sid = data['id'] = student_brain.getId
670            if reindex_special and 'review_state' in reindex_special:
671                modified = True
672                data['review_state'] = student_brain.review_state
[1707]673            sub_objects = False
674            for pt in reindextypes.keys():
[1702]675                modified = True
[1707]676                try:
677                    doc = getattr(student_object,self.affected_types[pt]['id']).getContent()
[2084]678                    #doc = sub_brains[pt].getObject().getContent()
679                    # path = "%s/%s" % (student_path,self.affected_types[pt]['id'])
680                    # doc = self.unrestrictedTraverse(path).getContent()
[1707]681                    sub_objects = True
682                except:
683                    continue
[2084]684                for field in set(name).intersection(self.affected_types[pt]['fields']):
[1707]685                    if hasattr(self,'get_from_doc_%s' % field):
[2078]686                        data[field] = getattr(self,'get_from_doc_%s' % field)(doc,
687                                                                              cached_data=cached_data)
[1707]688                    else:
689                        data[field] = getattr(doc,field)
690            if not sub_objects and noattr:
691                import_res = self.returning_import(id = sid)
692                if not import_res:
693                    continue
694                import_record = import_res[0]
695                data['matric_no'] = import_record.matric_no
696                data['sex'] = import_record.Sex == 'F'
697                data['name'] = "%s %s %s" % (import_record.Firstname,
698                                             import_record.Middlename,
699                                             import_record.Lastname)
[1815]700                data['jamb_reg_no'] = import_record.Entryregno
[1702]701            if reindex_special and 'registered_courses' in reindex_special:
[1954]702                try:
703                    study_course = getattr(student_object,"study_course")
704                    level_ids = study_course.objectIds()
705                except:
706                    continue
707                if not level_ids:
708                    continue
709                modified = True
710                level_ids.sort()
711                course_ids = getattr(study_course,level_ids[-1]).objectIds()
712                courses = []
713                for c in course_ids:
714                    if c.endswith('_co'):
715                        courses.append(c[:-3])
716                    else:
717                        courses.append(c)
718                data['registered_courses'] = courses
[1702]719            if modified:
720                self.modifyRecord(**data)
721        if pghandler: pghandler.finish()
722    ###)
[1620]723
724    def refreshCatalog(self, clear=0, pghandler=None): ###(
725        """ re-index everything we can find """
726        students_folder = self.portal_url.getPortalObject().campus.students
727        if clear:
[1724]728            self._catalog.clear()
[1700]729        students = self.portal_catalog(portal_type="Student")
730        num_objects = len(students)
[2078]731        cached_data = self.fill_certificates_dict()
[1620]732        if pghandler:
733            pghandler.init('Refreshing catalog: %s' % self.absolute_url(1), num_objects)
734        for i in xrange(num_objects):
735            if pghandler: pghandler.report(i)
[1700]736            student_brain = students[i]
737            spath = student_brain.getPath()
[1727]738            student_object = student_brain.getObject()
[1620]739            data = {}
[1700]740            sid = data['id'] = student_brain.getId
741            data['review_state'] = student_brain.review_state
[1707]742            sub_objects = False
743            for pt in self.affected_types.keys():
744                modified = True
745                try:
746                    doc = getattr(student_object,self.affected_types[pt]['id']).getContent()
747                    sub_objects = True
748                except:
[1727]749                    #from pdb import set_trace;set_trace()
[1707]750                    continue
751                for field in self.affected_types[pt]['fields']:
752                    if hasattr(self,'get_from_doc_%s' % field):
[2078]753                        data[field] = getattr(self,'get_from_doc_%s' % field)(doc,
754                                                                              cached_data=cached_data)
[1707]755                    else:
[1727]756                        data[field] = getattr(doc,field,None)
757            if not sub_objects:
[1700]758                import_res = self.returning_import(id = sid)
759                if not import_res:
[1620]760                    continue
[1700]761                import_record = import_res[0]
762                data['matric_no'] = import_record.matric_no
763                data['sex'] = import_record.Sex == 'F'
764                data['name'] = "%s %s %s" % (import_record.Firstname,
765                                             import_record.Middlename,
766                                             import_record.Lastname)
[1815]767                data['jamb_reg_no'] = import_record.Entryregno
[1727]768            else:
769                study_course = getattr(student_object,'study_course',None)
770                current_level = data.get('level',None)
771                data['registered_courses'] = []
772                if study_course and current_level and current_level in study_course.objectIds():
773                    level_obj = getattr(study_course,current_level)
[1749]774                    courses = []
[1727]775                    for c in level_obj.objectIds():
776                        if c.endswith('_co'):
777                            courses.append(c[:-3])
778                        else:
779                            courses.append(c)
[1749]780                    data['registered_courses'] = courses
[1700]781            self.addRecord(**data)
[1620]782        if pghandler: pghandler.finish()
783    ###)
784
[1700]785    security.declarePrivate('notify_event_listener') ###(
[1620]786    def notify_event_listener(self,event_type,object,infos):
787        "listen for events"
[1716]788        if not infos.has_key('rpath'):
789            return
[1702]790        pt = getattr(object,'portal_type',None)
791        mt = getattr(object,'meta_type',None)
[1954]792        students_catalog = self
[1702]793        data = {}
794        if pt == 'Student' and\
795           mt == 'CPS Proxy Folder' and\
796           event_type.startswith('workflow'):
797            data['id'] = object.getId()
798            data['review_state'] = self.portal_workflow.getInfoFor(object,'review_state',None)
799            students_catalog.modifyRecord(**data)
800            return
[1700]801        rpl = infos['rpath'].split('/')
[1731]802        if pt == 'Student' and mt == 'CPS Proxy Folder'\
803           and event_type == "sys_add_object":
[1700]804            student_id = object.id
805            try:
806                self.addRecord(id = student_id)
807            except ValueError:
808                pass
809            return
[1716]810        elif pt == 'StudentCourseResult' and mt == 'CPS Proxy Folder':
811            if event_type not in ("sys_add_object","sys_del_object"):
812                return
[2033]813            level_session = getattr(object.aq_parent.getContent(),'session','unknown')
814            if level_session not in (self.getSessionId()[-2:],'2006/2007'):
815                return
[1716]816            course_id = object.getId()
[1954]817            if course_id.endswith('_co'):
818                course_id = course_id[:-3]
[1716]819            student_id = object.absolute_url_path().split('/')[-4]
[1954]820            res = students_catalog(id = student_id)
[1716]821            if not res:
822                return
823            student_rec = res[0]
[2039]824            registered_courses = getattr(student_rec,'registered_courses',None)
825            if not registered_courses:
[1967]826                registered_courses = []
[2039]827            #import pdb;pdb.set_trace()
[1971]828            if event_type == "sys_add_object":
829                if course_id not in registered_courses:
830                    registered_courses.append(course_id)
831                else:
832                    return
[2039]833            elif registered_courses and event_type == "sys_del_object":
834                removed = False
[1954]835                while course_id in registered_courses:
[2039]836                    removed = True
[1954]837                    registered_courses.remove(course_id)
[2039]838                if not removed:
839                    return
[1716]840            data['id'] = student_id
841            data['registered_courses'] = registered_courses
[2069]842            self.modifyRecord(record = student_rec, **data)
[1971]843            return
[1716]844        if pt not in self.affected_types.keys():
[1700]845            return
[1716]846        if event_type not in ('sys_modify_object'):
847            return
[1700]848        if mt == 'CPS Proxy Folder':
849            return
[1716]850        for field in self.affected_types[pt]['fields']:
[1700]851            if hasattr(self,'get_from_doc_%s' % field):
852                data[field] = getattr(self,'get_from_doc_%s' % field)(object)
853            else:
854                data[field] = getattr(object,field)
855        data['id'] = rpl[2]
[1716]856        self.modifyRecord(**data)
[1700]857    ###)
[1620]858
[1625]859
[971]860InitializeClass(StudentsCatalog)
861
[1146]862###)
863
864class CoursesCatalog(WAeUPTable): ###(
[1716]865    security = ClassSecurityInfo()
[1146]866
867    meta_type = 'WAeUP Courses Catalog'
[2094]868    name =  "courses_catalog"
[1146]869    key = "code"
[2094]870    def __init__(self,name=None):
871        if name ==  None:
872            name =  self.name
873        WAeUPTable.__init__(self, name)
[1146]874
[1716]875    def manage_catalogReindex(self, REQUEST, RESPONSE, URL1): ###(
876        """ clear the catalog, then re-index everything """
[1146]877
[1716]878        elapse = time.time()
879        c_elapse = time.clock()
880
881        pgthreshold = self._getProgressThreshold()
882        handler = (pgthreshold > 0) and ZLogHandler(pgthreshold) or None
883        self.refreshCatalog(clear=1, pghandler=handler)
884
885        elapse = time.time() - elapse
886        c_elapse = time.clock() - c_elapse
887
888        RESPONSE.redirect(
889            URL1 +
890            '/manage_catalogAdvanced?manage_tabs_message=' +
891            urllib.quote('Catalog Updated \n'
892                         'Total time: %s\n'
893                         'Total CPU time: %s' % (`elapse`, `c_elapse`)))
894    ###)
895
896    def reindexIndex(self, name, REQUEST,pghandler=None): ###(
897        if isinstance(name, str):
898            name = (name,)
899        courses = self.portal_catalog(portal_type="Course")
900        num_objects = len(courses)
901        if pghandler:
902            pghandler.init('Refreshing catalog: %s' % self.absolute_url(1), num_objects)
903        for i in xrange(num_objects):
904            if pghandler: pghandler.report(i)
905            course_brain = courses[i]
906            course_object = course_brain.getObject()
907            pl = course_brain.getPath().split('/')
908            data = {}
909            cid = data[self.key] = course_brain.getId
910            data['faculty'] = pl[-4]
911            data['department'] = pl[-3]
912            doc = course_object.getContent()
913            for field in name:
914                if field not in (self.key,'faculty','department'):
915                    data[field] = getattr(doc,field)
916            self.modifyRecord(**data)
917        if pghandler: pghandler.finish()
918    ###)
919
920    def refreshCatalog(self, clear=0, pghandler=None): ###(
921        """ re-index everything we can find """
[1724]922        if clear:
923            self._catalog.clear()
[1716]924        courses = self.portal_catalog(portal_type="Course")
925        num_objects = len(courses)
926        if pghandler:
927            pghandler.init('Refreshing catalog: %s' % self.absolute_url(1), num_objects)
[1724]928        #from pdb import set_trace;set_trace()
[1716]929        for i in xrange(num_objects):
930            if pghandler: pghandler.report(i)
931            course_brain = courses[i]
[1724]932            course_doc = course_brain.getObject().getContent()
[1716]933            pl = course_brain.getPath().split('/')
934            data = {}
[1724]935            for field in self.schema():
[1749]936                data[field] = getattr(course_doc,field,None)
[1716]937            data[self.key] = course_brain.getId
[1724]938            ai = pl.index('academics')
939            data['faculty'] = pl[ai +1]
940            data['department'] = pl[ai +2]
941            if clear:
942                self.addRecord(**data)
943            else:
944                self.modifyRecord(**data)
[1716]945        if pghandler: pghandler.finish()
946    ###)
947
948    security.declarePrivate('notify_event_listener') ###(
949    def notify_event_listener(self,event_type,object,infos):
950        "listen for events"
951        if not infos.has_key('rpath'):
952            return
953        pt = getattr(object,'portal_type',None)
954        mt = getattr(object,'meta_type',None)
955        if pt != 'Course':
956            return
957        data = {}
958        rpl = infos['rpath'].split('/')
959        if event_type not in ("sys_add_object","sys_modify_object","sys_del_object"):
960            return
961        course_id = object.getId()
962        data[self.key] = course_id
[1724]963        if event_type == "sys_add_object" and mt == 'CPS Proxy Folder':
[1716]964            try:
965                self.addRecord(**data)
966            except ValueError:
[1724]967                return
968            course_id = object.getId()
969            doc = object.getContent()
970            if doc is None:
971                return
972            for field in self.schema():
[1749]973                data[field] = getattr(doc,field,None)
[1724]974            data[self.key] = course_id
975            ai = rpl.index('academics')
976            data['faculty'] = rpl[ai +1]
977            data['department'] = rpl[ai +2]
978            self.modifyRecord(**data)
979            return
[1716]980        if event_type == "sys_del_object":
981            self.deleteRecord(course_id)
[1724]982            return
[1716]983        if event_type == "sys_modify_object" and mt == 'Course':
[1724]984            #from pdb import set_trace;set_trace()
[1716]985            for field in self.schema():
[1749]986                data[field] = getattr(object,field,None)
[1716]987            course_id = object.aq_parent.getId()
988            data[self.key] = course_id
[1724]989            ai = rpl.index('academics')
990            data['faculty'] = rpl[ai +1]
991            data['department'] = rpl[ai +2]
[1716]992            self.modifyRecord(**data)
993    ###)
994
995
[1146]996InitializeClass(CoursesCatalog)
[1151]997###)
[1146]998
[2084]999class CourseResults(WAeUPTable): ###(
[2069]1000    security = ClassSecurityInfo()
1001
1002    meta_type = 'WAeUP Results Catalog'
1003    name = "course_results"
[2084]1004    key = "key" #student_id + level + course_id
[2094]1005    def __init__(self,name=None):
1006        if name ==  None:
1007            name = self.name
1008        WAeUPTable.__init__(self, name)
[2084]1009        self._queue = []
[2099]1010
[2084]1011    def addRecord(self, **data): ###(
[2094]1012        """add one record"""
[2099]1013
[2084]1014        uid = key = "%(student_id)s|%(level_id)s|%(course_id)s" % data
1015        if key in self._queue:
1016            return uid
1017        data['queue_status'] = ADDING_SHEDULED
1018        data['%s' % self.key] = uid
1019        res = self.searchResults({"%s" % self.key : uid})
1020        if len(res) > 0:
1021            raise ValueError("More than one record with uid %s" % uid)
1022        self.catalog_object(dict2ob(data), uid=uid)
1023        if not hasattr(self,'_queue'):
1024            self._queue = []
1025        self._queue.append(key)
1026        self._p_changed = 1
1027        return uid
1028    ###)
[2099]1029
[2094]1030    # def _p_resolveConflict(self, oldstate, committed, newstate):
1031    #     # Apply the changes made in going from old to newstate to
1032    #     # committed
[2099]1033
[2094]1034    #     # Note that in the case of undo, the olddata is the data for
1035    #     # the transaction being undone and newdata is the data for the
1036    #     # transaction previous to the undone transaction.
[2069]1037
[2094]1038    #     # Find the conflict policy on the new state to make sure changes
1039    #     # to it will be applied
1040
1041    #     # Committed is always the currently committed data.
1042    #     import pdb;pdb.set_trace()
1043    #     oldstate_data  =  oldstate['_queue']
1044    #     committed_data = committed['_queue']
1045    #     newstate_data  =  newstate['_queue']
1046
1047    #     # Merge newstate changes into committed
1048    #     for uid, new in newstate_data.items():
1049
1050    #         # Decide if this is a change
1051    #         old = oldstate_data.get(uid)
1052    #         current = committed_data.get(uid)
1053
1054
1055    def addMultipleRecords(self, records): ###(
1056        """add many records"""
1057        added_keys = []
1058        for data in records:
1059            uid = key = "%(student_id)s|%(level_id)s|%(course_id)s" % data
1060            added_keys.append(key)
1061            if key in self._queue:
1062                return uid
1063            data['queue_status'] = ADDING_SHEDULED
1064            data['%s' % self.key] = uid
1065            res = self.searchResults({"%s" % self.key : uid})
1066            if len(res) > 0:
1067                raise ValueError("More than one record with uid %s" % uid)
1068            self.catalog_object(dict2ob(data), uid=uid)
1069        if not hasattr(self,'_queue'):
1070            self._queue = added_keys
1071        self._queue.extend(added_keys)
1072        self._p_changed = 1
1073        return uid
1074    ###)
1075
[2084]1076    def deleteRecord(self, uid): ###(
1077        self.uncatalog_object(uid)
1078        if uid in self._queue:
1079            self._queue.remove(uid)
1080    ###)
1081
[2094]1082    def updateCourseResults(self,student_id,level_id,portal_catalog_results,course_results): ###(
[2099]1083        # query = Eq('path',"%s/campus/students/%s/study_course/%s" %
[2094]1084        #            (self.portal_url.getPortalPath(),
1085        #             student_id,
1086        #             level_id)) &\
1087        #             Eq('portal_type', "StudentCourseResult")
1088        # level_results = self.portal_catalog_real.evalAdvancedQuery(query)
[2099]1089        # level_results = [r for r in course_results
[2094]1090        #                  if level_id in r.relative_path.split('/')]
1091        course_results_ids = [cr.getId for cr in course_results]
1092        for r in portal_catalog_results:
1093            if r.getId in course_results_ids:
1094                continue
1095            course_result_doc = r.getObject().getContent()
1096            data = {}
1097            course_id = r.getId
1098            for field in self.schema():
1099                data[field] = getattr(course_result_doc,field,'')
1100            data['key'] = key = "%(student_id)s|%(level_id)s|%(course_id)s" % vars()
[2099]1101            data['student_id'] = student_id
1102            data['level_id'] = level_id
[2094]1103            data['queue_status'] = OBJECT_CREATED
[2099]1104            data['code'] = course_id
[2094]1105            self.catalog_object(dict2ob(data), uid=key)
1106        query = Eq('student_id',student_id) & Eq('level_id', level_id)
1107        return self.course_results.evalAdvancedQuery(query)
1108    ###)
1109
[2084]1110    def getCourses(self,student_id,level_id): ###(
[2094]1111        level_path = "%s/campus/students/%s/study_course/%s" % (self.portal_url.getPortalPath(),
1112                                                                student_id,
1113                                                                level_id)
1114        # portal_catalog_query = Eq('path',level_path) &\
1115        #                        Eq('portal_type', "StudentCourseResult")
1116        # portal_catalog_results = self.portal_catalog_real.evalAdvancedQuery(portal_catalog_query)
1117        portal_catalog_results = self.portal_catalog(path = level_path,
1118                                                     portal_type = "StudentCourseResult")
[2084]1119        query = Eq('student_id',student_id) & Eq('level_id', level_id)
[2094]1120        course_results = self.course_results.evalAdvancedQuery(query)
1121        if len(course_results) != len(portal_catalog_results):
1122            course_results = self.updateCourseResults(student_id,
1123                                                      level_id,
1124                                                      portal_catalog_results,
1125                                                      course_results)
[2084]1126        carry_overs = []
1127        normal = []
[2099]1128        credits = 0
[2094]1129        for brain in course_results:
[2084]1130            d = {}
[2099]1131            credits += int(brain.credits)
[2084]1132            for field in self.schema():
1133                d[field] = getattr(brain,field,'')
1134            d['sheduled'] = brain.queue_status == ADDING_SHEDULED
1135            d['coe'] = 'Elective'
1136            if brain.core_or_elective:
1137                d['coe'] = 'Core'
[2094]1138            id = code = d['id'] = brain.code
1139            is_carry_over = False
1140            if code.endswith('_co'):
1141                is_carry_over = True
1142                code = code[:-3]
1143            d['code'] = code
1144            d['title'] = self.courses_catalog.evalAdvancedQuery(Eq('code',code))[0].title
1145            if is_carry_over:
1146                d['coe'] = 'Core'
[2084]1147                carry_overs.append(d)
1148            else:
1149                normal.append(d)
1150        normal.sort(cmp=lambda x,y: cmp(x['semester'], y['semester']))
1151        carry_overs.sort(cmp=lambda x,y: cmp(x['semester'], y['semester']))
1152        return credits,carry_overs,normal
1153    ###)
1154
1155    def addObject(self,record): ###(
1156        key = record.key
1157        student_id,level_id,course_id = key.split('|')
1158        level = getattr(getattr(self.portal_url.getPortalObject().campus.students,student_id).study_course,level_id)
1159        cr_id = level.invokeFactory('StudentCourseResult', course_id)
1160        course_result = getattr(level,cr_id)
1161        self.portal_workflow.doActionFor(course_result,'open')
1162        d = {}
1163        for field in self.schema():
1164            d[field] = getattr(record,field,'')
1165        course_result.getContent().edit(mapping=d)
1166    ###)
[2099]1167
[2084]1168    security.declareProtected(ModifyPortalContent,"process_queue") ###(
1169    def process_queue(self,limit=None):
1170        """adds objects and removes them from the queue.
1171        If limit is specified, at most (limit) events are removed.
1172        """
1173        if not hasattr(self,'_queue'):
1174            return 0
1175        queue= self._queue
1176        if not limit or len(queue) <= limit:
1177            keys = self._queue[:]
1178        else:
1179            keys = queue[:limit]
1180        if not keys:
1181            records = self.evalAdvancedQuery(Eq('queue_status',ADDING_SHEDULED))
1182        else:
1183            records = self.evalAdvancedQuery(In("%s" % self.key,keys))
1184        for record in records:
1185            if record.queue_status == OBJECT_CREATED:
1186                continue
1187            self.addObject(record)
1188            data = {}
1189            data['key'] = record.key
1190            data['queue_status'] = OBJECT_CREATED
1191            self.modifyRecord(**data)
1192        count = 0
1193        for key in keys:
1194            count +=1
1195            if key in self._queue:
1196                self._queue.remove(key)
1197        self._p_changed = 1
1198        return count,len(self._queue)
1199    ###)
1200
1201    def manage_catalogClear(self, REQUEST=None, RESPONSE=None, URL1=None): ###(
1202        """ clears the whole enchilada """
1203        self._catalog.clear()
1204
1205        if REQUEST and RESPONSE:
1206            RESPONSE.redirect(
1207              URL1 +
1208              '/manage_catalogAdvanced?manage_tabs_message=Catalog%20Cleared')
1209    ###)
1210
[2069]1211    def manage_catalogReindex(self, REQUEST, RESPONSE, URL1): ###(
1212        """ clear the catalog, then re-index everything """
1213
1214        elapse = time.time()
1215        c_elapse = time.clock()
1216
1217        pgthreshold = self._getProgressThreshold()
1218        handler = (pgthreshold > 0) and ZLogHandler(pgthreshold) or None
[2084]1219        self.refreshCatalog(clear=1, pghandler=handler)
[2069]1220
1221        elapse = time.time() - elapse
1222        c_elapse = time.clock() - c_elapse
1223
1224        RESPONSE.redirect(
1225            URL1 +
1226            '/manage_catalogAdvanced?manage_tabs_message=' +
1227            urllib.quote('Catalog Updated \n'
1228                         'Total time: %s\n'
1229                         'Total CPU time: %s' % (`elapse`, `c_elapse`)))
1230    ###)
1231
[2084]1232    def refreshCatalog(self, clear=1, pghandler=None): ###(
1233        """ re-index everything we can find """
1234        students_folder = self.portal_url.getPortalObject().campus.students
1235        if clear:
1236            self._catalog.clear()
1237        course_results = self.portal_catalog(portal_type="StudentCourseResult")
1238        num_objects = len(course_results)
1239        if pghandler:
1240            pghandler.init('Refreshing catalog: %s' % self.absolute_url(1), num_objects)
1241        #import pdb;pdb.set_trace()
1242        for i in xrange(num_objects):
[2099]1243            if pghandler:
[2084]1244                pghandler.report(i)
1245            course_result_brain = course_results[i]
1246            path_list = course_result_brain.getPath().split('/')
[2094]1247            course_result_doc = course_result_brain.getObject().getContent()
[2084]1248            data = {}
1249            level_id = path_list[-2]
1250            course_id = path_list[-1]
1251            student_id = path_list[-4]
1252            for field in self.schema():
1253                data[field] = getattr(course_result_doc,field,'')
1254            data['key'] = key = "%(student_id)s|%(level_id)s|%(course_id)s" % vars()
[2099]1255            data['student_id'] = student_id
1256            data['level_id'] = level_id
[2084]1257            data['queue_status'] = OBJECT_CREATED
1258            self.catalog_object(dict2ob(data), uid=key)
1259        if pghandler: pghandler.finish()
1260    ###)
[2069]1261
[2084]1262    security.declarePrivate('notify_event_listener') ###(
1263    def notify_event_listener(self,event_type,object,infos):
1264        "listen for events"
1265        if not infos.has_key('rpath'):
1266            return
1267        pt = getattr(object,'portal_type',None)
1268        mt = getattr(object,'meta_type',None)
1269        data = {}
1270        rpl = infos['rpath'].split('/')
1271        if mt == 'CPS Proxy Folder':
1272            return
1273        if pt == 'StudentCourseResult' and event_type == "sys_modify_object":
1274            data["%s" % self.key] = uid = "%s|%s|%s" % (rpl[-5],rpl[-3],rpl[-2])
1275            records = self.searchResults({"%s" % self.key : uid})
1276            if len(records) > 1:
1277                # Can not happen, but anyway...
1278                raise ValueError("More than one record with uid %s" % uid)
1279            if len(records) == 0:
1280                raise KeyError("No record for uid %s" % uid)
1281            record = records[0]
1282            for field in ('core_or_elective','score'):
1283                value = getattr(object,field,None)
1284                data[field] = value
[2094]1285            try:
1286                self.modifyRecord(record,**data)
1287            except KeyError:
1288                pass
1289        if pt == 'StudentStudyLevel' and event_type == "sys_del_object":
1290            #import pdb;pdb.set_trace()
1291            student_id = rpl[-3]
1292            level_id = rpl[-1]
1293            res = self.searchResults(student_id = student_id,
1294                                     level_id = level_id)
1295            for cr in res:
1296                self.deleteRecord(cr.key)
[2084]1297    ###)
1298
1299InitializeClass(CourseResults)
[2069]1300###)
1301
[1625]1302class OnlinePaymentsImport(WAeUPTable): ###(
[1620]1303
1304    meta_type = 'WAeUP Online Payment Transactions'
[1625]1305    name = "online_payments_import"
[1620]1306    key = "order_id"
[2094]1307    def __init__(self,name=None):
1308        if name ==  None:
1309            name = self.name
1310        WAeUPTable.__init__(self, name)
[1620]1311
1312
[2069]1313InitializeClass(OnlinePaymentsImport)
[1620]1314###)
1315
[1151]1316class ReturningImport(WAeUPTable): ###(
[1146]1317
[1151]1318    meta_type = 'Returning Import Table'
1319    name = "returning_import"
[1146]1320    key = "matric_no"
[2094]1321    def __init__(self,name=None):
1322        if name ==  None:
1323            name = self.name
1324        WAeUPTable.__init__(self, name)
[1146]1325
1326
[1151]1327InitializeClass(ReturningImport)
1328###)
[1146]1329
1330class ResultsImport(WAeUPTable): ###(
1331
1332    meta_type = 'Results Import Table'
1333    name = "results_import"
1334    key = "key"
[2094]1335    def __init__(self,name=None):
1336        if name ==  None:
1337            name = self.name
1338        WAeUPTable.__init__(self, name)
[1146]1339
1340
1341InitializeClass(ResultsImport)
1342
1343###)
1344
1345class PaymentsCatalog(WAeUPTable): ###(
1346
1347    meta_type = 'WAeUP Payments Catalog'
1348    name = "students_catalog"
1349    key = "id"
[2094]1350    def __init__(self,name=None):
1351        if name ==  None:
1352            name = self.name
1353        WAeUPTable.__init__(self, name)
[1146]1354
1355
1356InitializeClass(PaymentsCatalog)
1357
1358###)
1359
[414]1360# BBB:
1361AccomodationTable = AccommodationTable
Note: See TracBrowser for help on using the repository browser.