#-*- mode: python; mode: fold -*- # (C) Copyright 2005 AixtraWare # Author: Joachim Schmitz # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as published # by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # # $Id: WAeUPTables.py 1686 2007-04-14 13:21:49Z joachim $ from zope.interface import implements from Globals import InitializeClass from Products.ZCatalog.ZCatalog import ZCatalog from Products.ZCatalog.ProgressHandler import ZLogHandler from AccessControl import ClassSecurityInfo from Products.CMFCore.permissions import ModifyPortalContent import DateTime,time import csv,re import logging import Globals p_home = Globals.package_home(globals()) i_home = Globals.INSTANCE_HOME from interfaces import IWAeUPTable class AttributeHolder(object): pass def dict2ob(dict): ob = AttributeHolder() for key, value in dict.items(): setattr(ob, key, value) return ob class WAeUPTable(ZCatalog): ###( implements(IWAeUPTable) security = ClassSecurityInfo() def refreshCatalog(self, clear=0, pghandler=None): """ don't refresh for a normal table """ if self.REQUEST and self.REQUEST.RESPONSE: self.REQUEST.RESPONSE.redirect( URL1 + '/manage_catalogAdvanced?manage_tabs_message=Catalog%20refresh%20not%20implemented') def manage_catalogClear(self, REQUEST=None, RESPONSE=None, URL1=None): """ clears the whole enchilada """ #self._catalog.clear() if REQUEST and RESPONSE: RESPONSE.redirect( URL1 + '/manage_catalogAdvanced?manage_tabs_message=Catalog%20Clearing%20disabled') def addRecord(self, **data): # The uid is the same as "bed". uid = data[self.key] res = self.searchResults({"%s" % self.key : uid}) if len(res) > 0: raise ValueError("More than one record with uid %s" % uid) self.catalog_object(dict2ob(data), uid=uid) return uid def deleteRecord(self, uid): #import pdb;pdb.set_trace() self.uncatalog_object(uid) def searchAndSetRecord(self, **data): raise NotImplemented def modifyRecord(self, **data): #records = self.searchResults(uid=uid) uid = data[self.key] records = self.searchResults({"%s" % self.key : uid}) if len(records) > 1: # Can not happen, but anyway... raise ValueError("More than one record with uid %s" % uid) if len(records) == 0: raise KeyError("No record for uid %s" % uid) record = records[0] record_data = {} for field in self.schema() + self.indexes(): record_data[field] = getattr(record, field) # Add the updated data: record_data.update(data) self.catalog_object(dict2ob(record_data), uid) def reindexIndex(self, name, REQUEST,pghandler=None): if isinstance(name, str): name = (name,) paths = self._catalog.uids.items() i = 0 #import pdb;pdb.set_trace() for p,rid in paths: i += 1 metadata = self.getMetadataForRID(rid) record_data = {} for field in name: record_data[field] = metadata.get(field) uid = metadata.get(self.key) self.catalog_object(dict2ob(record_data), uid, idxs=name, update_metadata=0) security.declareProtected(ModifyPortalContent,"exportAllRecords") def exportAllRecords(self): "export a WAeUPTable" #import pdb;pdb.set_trace() fields = [field for field in self.schema()] format = ','.join(['"%%(%s)s"' % fn for fn in fields]) csv = [] csv.append(','.join(['"%s"' % fn for fn in fields])) for uid in self._catalog.uids: records = self.searchResults({"%s" % self.key : uid}) if len(records) > 1: # Can not happen, but anyway... raise ValueError("More than one record with uid %s" % uid) if len(records) == 0: raise KeyError("No record for uid %s" % uid) rec = records[0] csv.append(format % rec) current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S") open("%s/import/%s-%s.csv" % (i_home,self.getId(),current),"w+").write('\n'.join(csv)) ###) class AccommodationTable(WAeUPTable): ###( meta_type = 'WAeUP Accommodation Tool' name = "accommodation" key = "bed" def __init__(self): WAeUPTable.__init__(self, 'portal_accommodation') def searchAndReserveBed(self, student_id,bed_type): records = self.searchResults({'student' : student_id}) if len(records) > 0: return -1,"Student with Id %s already booked bed %s." % (student_id,records[0].bed) records = [r for r in self.searchResults({'bed_type' : bed_type}) if not r.student] #import pdb;pdb.set_trace() if len(records) == 0: return -2,"No bed available" rec = records[0] self.modifyRecord(bed=rec.bed,student=student_id) s_logger = logging.getLogger('WAeUPTables.AccommodationTable.searchAndReserveBed') s_logger.info('%s reserved bed %s' % (student_id,rec.bed)) return 1,rec.bed InitializeClass(AccommodationTable) ###) class PinTable(WAeUPTable): ###( from ZODB.POSException import ConflictError meta_type = 'WAeUP Pin Tool' name = "pins" key = 'pin' def __init__(self): WAeUPTable.__init__(self, 'portal_pins') def searchAndSetRecord(self, uid, student_id,prefix): #records = self.searchResults(uid=uid) records = self.searchResults(student = student_id) #import pdb;pdb.set_trace() if len(records) > 0: for r in records: if r.pin != uid and r.prefix_batch.startswith(prefix): return -2 records = self.searchResults({"%s" % self.key : uid}) if len(records) > 1: # Can not happen, but anyway... raise ValueError("More than one record with uid %s" % uid) if len(records) == 0: return -1 record = records[0] if record.student == "": record_data = {} for field in self.schema() + self.indexes(): record_data[field] = getattr(record, field) # Add the updated data: record_data['student'] = student_id try: self.catalog_object(dict2ob(record_data), uid) return 1 except ConflictError: return 2 if record.student.upper() != student_id.upper(): return 0 if record.student.upper() == student_id.upper(): return 2 return -3 InitializeClass(PinTable) ###) class PumeResultsTable(WAeUPTable): ###( meta_type = 'WAeUP PumeResults Tool' name = "pumeresults" key = "jamb_reg_no" def __init__(self): WAeUPTable.__init__(self, 'portal_pumeresults') InitializeClass(PumeResultsTable) ###) class StudentsCatalog(WAeUPTable): ###( security = ClassSecurityInfo() meta_type = 'WAeUP Students Catalog' name = "students_catalog" key = "id" interesting_types = ('Student', 'StudentApplication', 'StudentCLearance', 'StudentPersonal', 'StudentStudyCourse', ) def __init__(self): WAeUPTable.__init__(self, 'students_catalog') return def get_review_state(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc): ###( "return the students review_state from portal_catalog" cat_res = self.portal_catalog(id = sid) if len(cat_res) != 1: return None return cat_res[0].review_state def get_course(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc): "return the students study_course" if study_course_doc is None: return None return getattr(study_course_doc,'study_course',None) def get_department(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc): "return the students department" if study_course_doc is None: return None certificate_res = self.portal_catalog(id = study_course_doc.study_course) if len(certificate_res) != 1: return None return certificate_res[0].getPath().split('/')[-3] def get_email(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc): "return the students email from the personal" if personal_doc is None: return None return getattr(personal_doc,'email',None) def get_entry_mode(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc): "return the students entry_mode from the application" if application_doc is None: return None return getattr(application_doc,'entry_mode',None) def get_jamb_reg_no(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc): "return the students jamb_reg_no from the application" if application_doc is None: return None return getattr(application_doc,'jamb_reg_no',None) def get_faculty(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc): "return the students faculty" if study_course_doc is None: return None certificate_res = self.portal_catalog(id = study_course_doc.study_course) if len(certificate_res) != 1: return None return certificate_res[0].getPath().split('/')[-4] def get_level(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc): "return the students study_course" if study_course_doc is None: return None #from pdb import set_trace;set_trace() return getattr(study_course_doc,'current_level',None) def get_matric_no(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc): "return the students matric_no from the clearance " if clearance_doc is None: return None return getattr(clearance_doc,'matric_no',None) def get_name(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc): "return the students name from the personal" if personal_doc is None: return None doc = personal_doc return "%s %s %s" % (doc.firstname,doc.middlename,doc.lastname) def get_phone(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc): "return the students phone from the personal" if personal_doc is None: return None return getattr(personal_doc,'phone',None) def get_sex(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc): "return the students sex from the personal" if personal_doc is None: return None return getattr(personal_doc,'sex',None) def get_verdict(self,sid,application_doc,clearance_doc,personal_doc,study_course_doc): "return the students study_course" if study_course_doc is None: return None return getattr(study_course_doc,'current_verdict',None) ###) def refreshCatalog(self, clear=0, pghandler=None): ###( """ re-index everything we can find """ students_folder = self.portal_url.getPortalObject().campus.students cat = self._catalog paths = self._catalog.uids.items() if clear: paths = tuple(paths) cat.clear() num_objects = len(paths) if pghandler: pghandler.init('Refreshing catalog: %s' % self.absolute_url(1), num_objects) for i in xrange(num_objects): if pghandler: pghandler.report(i) p = paths[i] sid = p[0] pcat_res = self.portal_catalog(id=sid) if len(pcat_res) != 1: continue student_brain = pcat_res[0] student_obj = student_brain.getObject() if student_obj.hasObject('application'): application_doc = getattr(student_obj,'application').getContent() else: application_doc = None if student_obj.hasObject('clearance'): clearance_doc = getattr(student_obj,'clearance').getContent() else: clearance_doc = None if student_obj.hasObject('personal'): personal_doc = getattr(student_obj,'personal').getContent() else: personal_doc = None if student_obj.hasObject('study_course'): study_course_doc = getattr(student_obj,'study_course').getContent() else: study_course_doc = None data = {} data['id'] = sid for field in self.schema(): function = getattr(self,"get_%s" % field, None) if function is None: continue value = function(sid,application_doc,clearance_doc,personal_doc,study_course_doc) if value is not None: data[field] = value self.modifyRecord(**data) if pghandler: pghandler.finish() ###) def manage_catalogReindex(self, REQUEST, RESPONSE, URL1): """ clear the catalog, then re-index everything """ elapse = time.time() c_elapse = time.clock() pgthreshold = self._getProgressThreshold() handler = (pgthreshold > 0) and ZLogHandler(pgthreshold) or None self.refreshCatalog(clear=0, pghandler=handler) elapse = time.time() - elapse c_elapse = time.clock() - c_elapse RESPONSE.redirect( URL1 + '/manage_catalogAdvanced?manage_tabs_message=' + urllib.quote('Catalog Updated \n' 'Total time: %s\n' 'Total CPU time: %s' % (`elapse`, `c_elapse`))) security.declarePrivate('notify_event_listener') def notify_event_listener(self,event_type,object,infos): "listen for events" pt = object.portal_type mt = object.meta_type students_catalog = self.students_catalog #if pt not in self.interesting_types: # return #print "%(pt)s\n %(event_type)s \n %(infos)s\n" % vars() if not infos.has_key('rpath'): return if pt == 'Student' and event_type == "workflow": pass elif mt == 'StudentApplication': if event_type not in ('sys_modify_object'): return print "%(pt)s\n %(event_type)s \n %(infos)s\n" % vars() from pdb import set_trace;set_trace() jamb_reg_no = getattr(object,'jamb_reg_no',None) if jamb_reg_no is None: return student_id = infos['rpath'].split('/')[2] self.fixName(student_id) student_entry = students_catalog(id = student_id)[0] if student_entry.jamb_reg_no == jamb_reg_no: return students_catalog.modifyRecord(id = student_id, jamb_reg_no = jamb_reg_no) elif mt == 'StudentPersonal': if event_type not in ('sys_modify_object'): return print "%(pt)s\n %(event_type)s \n %(infos)s\n" % vars() student_id = infos['rpath'].split('/')[2] self.fixName(student_id) InitializeClass(StudentsCatalog) ###) class CoursesCatalog(WAeUPTable): ###( meta_type = 'WAeUP Courses Catalog' name = "students_catalog" key = "code" def __init__(self): WAeUPTable.__init__(self, 'courses_catalog') InitializeClass(CoursesCatalog) ###) class OnlinePaymentsImport(WAeUPTable): ###( meta_type = 'WAeUP Online Payment Transactions' name = "online_payments_import" key = "order_id" def __init__(self): WAeUPTable.__init__(self, self.name) InitializeClass(CoursesCatalog) ###) class ReturningImport(WAeUPTable): ###( meta_type = 'Returning Import Table' name = "returning_import" key = "matric_no" def __init__(self): WAeUPTable.__init__(self, 'returning_import') InitializeClass(ReturningImport) ###) class ResultsImport(WAeUPTable): ###( meta_type = 'Results Import Table' name = "results_import" key = "key" def __init__(self): WAeUPTable.__init__(self, 'results_import') InitializeClass(ResultsImport) ###) class PaymentsCatalog(WAeUPTable): ###( meta_type = 'WAeUP Payments Catalog' name = "students_catalog" key = "id" def __init__(self): WAeUPTable.__init__(self, 'payments_catalog') InitializeClass(PaymentsCatalog) ###) # BBB: AccomodationTable = AccommodationTable