source: WAeUP_SRP/branches/uli/WAeUPTables.py @ 17937

Last change on this file since 17937 was 1653, checked in by uli, 18 years ago

Incorporated changeset 1593:1652 of trunk into uli-branch.

  • Property svn:keywords set to Id
File size: 17.1 KB
Line 
1#-*- mode: python; mode: fold -*-
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 1653 2007-03-28 02:35:25Z uli $
20
21from zope.interface import implements
22from Globals import InitializeClass
23from Products.ZCatalog.ZCatalog import ZCatalog
24from Products.ZCatalog.ProgressHandler import ZLogHandler
25from AccessControl import ClassSecurityInfo
26from Products.CMFCore.permissions import ModifyPortalContent
27
28import DateTime,time
29import csv,re
30import logging
31import Globals
32p_home = Globals.package_home(globals())
33i_home = Globals.INSTANCE_HOME
34
35from interfaces import IWAeUPTable
36
37class AttributeHolder(object):
38    pass
39
40def dict2ob(dict):
41    ob = AttributeHolder()
42    for key, value in dict.items():
43        setattr(ob, key, value)
44    return ob
45
46
47class WAeUPTable(ZCatalog): ###(
48
49    implements(IWAeUPTable)
50    security = ClassSecurityInfo()
51
52    def refreshCatalog(self, clear=0, pghandler=None):
53        """ don't refresh for a normal table """
54
55        if self.REQUEST and self.REQUEST.RESPONSE:
56            self.REQUEST.RESPONSE.redirect(
57              URL1 +
58              '/manage_catalogAdvanced?manage_tabs_message=Catalog%20refresh%20not%20implemented')
59
60    def manage_catalogClear(self, REQUEST=None, RESPONSE=None, URL1=None):
61        """ clears the whole enchilada """
62        #self._catalog.clear()
63
64        if REQUEST and RESPONSE:
65            RESPONSE.redirect(
66              URL1 +
67              '/manage_catalogAdvanced?manage_tabs_message=Catalog%20Clearing%20disabled')
68
69    def addRecord(self, **data):
70        # The uid is the same as "bed".
71        uid = data[self.key]
72        res = self.searchResults({"%s" % self.key : uid})
73        if len(res) > 0:
74            raise ValueError("More than one record with uid %s" % uid)
75        self.catalog_object(dict2ob(data), uid=uid)
76        return uid
77
78    def deleteRecord(self, uid):
79        #import pdb;pdb.set_trace()
80        self.uncatalog_object(uid)
81
82    def searchAndSetRecord(self, **data):
83        raise NotImplemented
84
85    def modifyRecord(self, **data):
86        #records = self.searchResults(uid=uid)
87        uid = data[self.key]
88        records = self.searchResults({"%s" % self.key : uid})
89        if len(records) > 1:
90            # Can not happen, but anyway...
91            raise ValueError("More than one record with uid %s" % uid)
92        if len(records) == 0:
93            raise KeyError("No record for uid %s" % uid)
94        record = records[0]
95        record_data = {}
96        for field in self.schema() + self.indexes():
97            record_data[field] = getattr(record, field)
98        # Add the updated data:
99        record_data.update(data)
100        self.catalog_object(dict2ob(record_data), uid)
101
102    def reindexIndex(self, name, REQUEST,pghandler=None):
103        if isinstance(name, str):
104            name = (name,)
105        paths = self._catalog.uids.items()
106        i = 0
107        #import pdb;pdb.set_trace()
108        for p,rid in paths:
109            i += 1
110            metadata = self.getMetadataForRID(rid)
111            record_data = {}
112            for field in name:
113                record_data[field] = metadata.get(field)
114            uid = metadata.get(self.key)
115            self.catalog_object(dict2ob(record_data), uid, idxs=name,
116                                update_metadata=0)
117
118    security.declareProtected(ModifyPortalContent,"exportAllRecords")
119    def exportAllRecords(self):
120        "export a WAeUPTable"
121        #import pdb;pdb.set_trace()
122        fields = [field for field in self.schema()]
123        format = ','.join(['"%%(%s)s"' % fn for fn in fields])
124        csv = []
125        csv.append(','.join(['"%s"' % fn for fn in fields]))
126        for uid in self._catalog.uids:
127            records = self.searchResults({"%s" % self.key : uid})
128            if len(records) > 1:
129                # Can not happen, but anyway...
130                raise ValueError("More than one record with uid %s" % uid)
131            if len(records) == 0:
132                raise KeyError("No record for uid %s" % uid)
133            rec = records[0]
134            csv.append(format % rec)
135        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
136        open("%s/import/%s-%s.csv" % (i_home,self.getId(),current),"w+").write('\n'.join(csv))
137
138###)
139
140class AccommodationTable(WAeUPTable): ###(
141
142    meta_type = 'WAeUP Accommodation Tool'
143    name = "accommodation"
144    key = "bed"
145    def __init__(self):
146        WAeUPTable.__init__(self, 'portal_accommodation')
147
148    def searchAndReserveBed(self, student_id,bed_type):
149        records = self.searchResults({'student' : student_id})
150        if len(records) > 0:
151            return -1,"Student with Id %s already booked bed %s." % (student_id,records[0].bed)
152
153        records = [r for r in self.searchResults({'bed_type' : bed_type}) if not r.student]
154        #import pdb;pdb.set_trace()
155        if len(records) == 0:
156            return -2,"No bed available"
157        rec = records[0]
158        self.modifyRecord(bed=rec.bed,student=student_id)
159        s_logger = logging.getLogger('WAeUPTables.AccommodationTable.searchAndReserveBed')
160        s_logger.info('%s reserved bed %s' % (student_id,rec.bed))
161        return 1,rec.bed
162
163
164InitializeClass(AccommodationTable)
165
166###)
167
168class PinTable(WAeUPTable): ###(
169    from ZODB.POSException import ConflictError
170    meta_type = 'WAeUP Pin Tool'
171    name = "pins"
172    key = 'pin'
173    def __init__(self):
174        WAeUPTable.__init__(self, 'portal_pins')
175
176
177    def searchAndSetRecord(self, uid, student_id,prefix):
178        #records = self.searchResults(uid=uid)
179        records = self.searchResults(student = student_id)
180        #import pdb;pdb.set_trace()
181        if len(records) > 0:
182            for r in records:
183                if r.pin != uid and r.prefix_batch.startswith(prefix):
184                    return -2
185        records = self.searchResults({"%s" % self.key : uid})
186        if len(records) > 1:
187            # Can not happen, but anyway...
188            raise ValueError("More than one record with uid %s" % uid)
189        if len(records) == 0:
190            return -1
191        record = records[0]
192        if record.student == "":
193            record_data = {}
194            for field in self.schema() + self.indexes():
195                record_data[field] = getattr(record, field)
196            # Add the updated data:
197            record_data['student'] = student_id
198            try:
199                self.catalog_object(dict2ob(record_data), uid)
200                return 1
201            except ConflictError:
202                return 2
203        if record.student.upper() != student_id.upper():
204            return 0
205        if record.student.upper() == student_id.upper():
206            return 2
207        return -3
208
209InitializeClass(PinTable)
210
211###)
212
213class PumeResultsTable(WAeUPTable): ###(
214
215    meta_type = 'WAeUP PumeResults Tool'
216    name = "pumeresults"
217    key = "jamb_reg_no"
218    def __init__(self):
219        WAeUPTable.__init__(self, 'portal_pumeresults')
220
221
222InitializeClass(PumeResultsTable)
223
224###)
225
226class StudentsCatalog(WAeUPTable): ###(
227    security = ClassSecurityInfo()
228
229    meta_type = 'WAeUP Students Catalog'
230    name = "students_catalog"
231    key = "id"
232    interesting_types = ('Student',
233                         'StudentApplication',
234                         'StudentCLearance',
235                         'StudentPersonal',
236                         'StudentStudyCourse',
237                         )
238
239    def __init__(self):
240        WAeUPTable.__init__(self, 'students_catalog')
241        return
242
243    def get_review_state(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc): ###(
244        "return the students review_state from portal_catalog"
245        cat_res = self.portal_catalog(id = sid)
246        if len(cat_res) != 1:
247            return None
248        return cat_res[0].review_state
249
250    def get_course(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc):
251        "return the students study_course"
252        if study_course_doc is None:
253            return None
254        return getattr(study_course_doc,'study_course',None)
255
256    def get_department(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc):
257        "return the students department"
258        if study_course_doc is None:
259            return None
260        certificate_res = self.portal_catalog(id = study_course_doc.study_course)
261        if len(certificate_res) != 1:
262            return None
263        return certificate_res[0].getPath().split('/')[-3]
264
265    def get_email(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc):
266        "return the students email from the personal"
267        if personal_doc is None:
268            return None
269        return getattr(personal_doc,'email',None)
270
271    def get_entry_mode(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc):
272        "return the students entry_mode from the application"
273        if application_doc is None:
274            return None
275        return getattr(application_doc,'entry_mode',None)
276
277    def get_jamb_reg_no(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc):
278        "return the students jamb_reg_no from the application"
279        if application_doc is None:
280            return None
281        return getattr(application_doc,'jamb_reg_no',None)
282
283    def get_faculty(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc):
284        "return the students faculty"
285        if study_course_doc is None:
286            return None
287        certificate_res = self.portal_catalog(id = study_course_doc.study_course)
288        if len(certificate_res) != 1:
289            return None
290        return certificate_res[0].getPath().split('/')[-4]
291
292    def get_level(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc):
293        "return the students study_course"
294        if study_course_doc is None:
295            return None
296        #from pdb import set_trace;set_trace()
297        return getattr(study_course_doc,'current_level',None)
298
299    def get_matric_no(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc):
300        "return the students matric_no from the clearance "
301        if clearance_doc is None:
302            return None
303        return getattr(clearance_doc,'matric_no',None)
304
305    def get_name(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc):
306        "return the students name from the personal"
307        if personal_doc is None:
308            return None
309        doc = personal_doc
310        return "%s %s %s" % (doc.firstname,doc.middlename,doc.lastname)
311
312    def get_phone(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc):
313        "return the students phone from the personal"
314        if personal_doc is None:
315            return None
316        return getattr(personal_doc,'phone',None)
317
318    def get_sex(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc):
319        "return the students sex from the personal"
320        if personal_doc is None:
321            return None
322        return getattr(personal_doc,'sex',None)
323
324    def get_verdict(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc):
325        "return the students study_course"
326        if study_course_doc is None:
327            return None
328        return getattr(study_course_doc,'current_verdict',None)
329    ###)
330
331    def refreshCatalog(self, clear=0, pghandler=None): ###(
332        """ re-index everything we can find """
333        students_folder = self.portal_url.getPortalObject().campus.students
334
335        cat = self._catalog
336        paths = self._catalog.uids.items()
337        if clear:
338            paths = tuple(paths)
339            cat.clear()
340
341        num_objects = len(paths)
342        if pghandler:
343            pghandler.init('Refreshing catalog: %s' % self.absolute_url(1), num_objects)
344        for i in xrange(num_objects):
345            if pghandler: pghandler.report(i)
346            p = paths[i]
347            sid = p[0]
348            pcat_res = self.portal_catalog(id=sid)
349            if len(pcat_res) != 1:
350                continue
351            student_brain = pcat_res[0]
352            student_obj = student_brain.getObject()
353            if student_obj.hasObject('application'):
354                application_doc = getattr(student_obj,'application').getContent()
355            else:
356                application_doc = None
357            if student_obj.hasObject('clearance'):
358                clearance_doc = getattr(student_obj,'clearance').getContent()
359            else:
360                clearance_doc = None
361            if student_obj.hasObject('personal'):
362                personal_doc = getattr(student_obj,'personal').getContent()
363            else:
364                personal_doc = None
365            if student_obj.hasObject('study_course'):
366                study_course_doc = getattr(student_obj,'study_course').getContent()
367            else:
368                study_course_doc = None
369            data = {}
370            data['id'] = sid
371            for field in self.schema():
372                function = getattr(self,"get_%s" % field, None)
373                if function is None:
374                    continue
375                value = function(sid,application_doc,clearance_doc,personal_doc,study_course_doc)
376                if value is not None:
377                    data[field] = value
378            self.modifyRecord(**data)
379        if pghandler: pghandler.finish()
380    ###)
381
382    def manage_catalogReindex(self, REQUEST, RESPONSE, URL1):
383        """ clear the catalog, then re-index everything """
384
385        elapse = time.time()
386        c_elapse = time.clock()
387
388        pgthreshold = self._getProgressThreshold()
389        handler = (pgthreshold > 0) and ZLogHandler(pgthreshold) or None
390        self.refreshCatalog(clear=0, pghandler=handler)
391
392        elapse = time.time() - elapse
393        c_elapse = time.clock() - c_elapse
394
395        RESPONSE.redirect(
396            URL1 +
397            '/manage_catalogAdvanced?manage_tabs_message=' +
398            urllib.quote('Catalog Updated \n'
399                         'Total time: %s\n'
400                         'Total CPU time: %s' % (`elapse`, `c_elapse`)))
401
402
403    security.declarePrivate('notify_event_listener')
404    def notify_event_listener(self,event_type,object,infos):
405        "listen for events"
406        pt = object.portal_type
407        mt = object.meta_type
408        students_catalog = self.students_catalog
409        #if pt not in self.interesting_types:
410        #    return
411        #print "%(pt)s\n %(event_type)s \n %(infos)s\n" % vars()
412        if not infos.has_key('rpath'):
413            return
414        if pt == 'Student' and event_type == "workflow":
415            pass
416        elif mt == 'StudentApplication':
417            if event_type not in ('sys_modify_object'):
418                return
419            print "%(pt)s\n %(event_type)s \n %(infos)s\n" % vars()
420            from pdb import set_trace;set_trace()
421            jamb_reg_no = getattr(object,'jamb_reg_no',None)
422            if jamb_reg_no is None:
423                return
424            student_id = infos['rpath'].split('/')[2]
425            self.fixName(student_id)
426            student_entry = students_catalog(id = student_id)[0]
427            if student_entry.jamb_reg_no == jamb_reg_no:
428                return
429            students_catalog.modifyRecord(id = student_id,
430                                          jamb_reg_no = jamb_reg_no)
431        elif mt == 'StudentPersonal':
432            if event_type not in ('sys_modify_object'):
433                return
434            print "%(pt)s\n %(event_type)s \n %(infos)s\n" % vars()
435            student_id = infos['rpath'].split('/')[2]
436            self.fixName(student_id)
437
438
439InitializeClass(StudentsCatalog)
440
441###)
442
443class CoursesCatalog(WAeUPTable): ###(
444
445    meta_type = 'WAeUP Courses Catalog'
446    name = "students_catalog"
447    key = "code"
448    def __init__(self):
449        WAeUPTable.__init__(self, 'courses_catalog')
450
451
452InitializeClass(CoursesCatalog)
453###)
454
455class OnlinePaymentsImport(WAeUPTable): ###(
456
457    meta_type = 'WAeUP Online Payment Transactions'
458    name = "online_payments_import"
459    key = "order_id"
460    def __init__(self):
461        WAeUPTable.__init__(self, self.name)
462
463
464InitializeClass(CoursesCatalog)
465###)
466
467class ReturningImport(WAeUPTable): ###(
468
469    meta_type = 'Returning Import Table'
470    name = "returning_import"
471    key = "matric_no"
472    def __init__(self):
473        WAeUPTable.__init__(self, 'returning_import')
474
475
476InitializeClass(ReturningImport)
477###)
478
479class ResultsImport(WAeUPTable): ###(
480
481    meta_type = 'Results Import Table'
482    name = "results_import"
483    key = "key"
484    def __init__(self):
485        WAeUPTable.__init__(self, 'results_import')
486
487
488InitializeClass(ResultsImport)
489
490###)
491
492class PaymentsCatalog(WAeUPTable): ###(
493
494    meta_type = 'WAeUP Payments Catalog'
495    name = "students_catalog"
496    key = "id"
497    def __init__(self):
498        WAeUPTable.__init__(self, 'payments_catalog')
499
500
501InitializeClass(PaymentsCatalog)
502
503###)
504
505# BBB:
506AccomodationTable = AccommodationTable
Note: See TracBrowser for help on using the repository browser.