source: WAeUP_SRP/trunk/WAeUPTables.py @ 2109

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

some corrections (see email 'Befund')

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