Index: /WAeUP_SRP/trunk/profiles/futminna/actions.xml
===================================================================
--- /WAeUP_SRP/trunk/profiles/futminna/actions.xml	(revision 5780)
+++ /WAeUP_SRP/trunk/profiles/futminna/actions.xml	(revision 5781)
@@ -8,3 +8,8 @@
   </action>
  </action-provider>
+ <action-provider name="portal_actions">
+  <action title="My Accommodation" action_id="reserve_accommodation"
+     category="student_navigation" condition_expr="member"
+     url_expr="string:${portal_url}/campus/students/${member}/accommodations" visible="True"/>
+ </action-provider> 
 </object>
Index: /WAeUP_SRP/trunk/skins/waeup_accommodation/ReadMe.txt
===================================================================
--- /WAeUP_SRP/trunk/skins/waeup_accommodation/ReadMe.txt	(revision 5780)
+++ /WAeUP_SRP/trunk/skins/waeup_accommodation/ReadMe.txt	(revision 5781)
@@ -35,5 +35,5 @@
 Profile importieren (Achtung: vorher Portalbasisdaten sichern)
 initialize_accommodation_catalog
-getStudentFolderInfo Zeile 84,58 aktivieren
+getStudentFolderInfo Zeile 84,85 aktivieren
 student_view.pt: in Zeile 63 condition entfernen
 random Order für Okene customisieren
@@ -44,2 +44,3 @@
 Beim Löschen von Studenten accommodation-Tabelle exportieren
 Online Payment auf FUTMinna implementieren
+Accommodation.AccoFolder.importReservedBeds anpassen
Index: /WAeUP_SRP/trunk/skins/waeup_accommodation/getAccommodationStatus.py
===================================================================
--- /WAeUP_SRP/trunk/skins/waeup_accommodation/getAccommodationStatus.py	(revision 5780)
+++ /WAeUP_SRP/trunk/skins/waeup_accommodation/getAccommodationStatus.py	(revision 5781)
@@ -177,4 +177,5 @@
 info['bed'] = accommodation_record.bed
 info['session'] = accommodation_record.session
+info['maintenance_paid'] = accommodation_record.reservation_status == 'maintenance_fee_paid'
 
 return info
Index: /WAeUP_SRP/trunk/skins/waeup_accommodation/pay_accommodation_form.pt
===================================================================
--- /WAeUP_SRP/trunk/skins/waeup_accommodation/pay_accommodation_form.pt	(revision 5780)
+++ /WAeUP_SRP/trunk/skins/waeup_accommodation/pay_accommodation_form.pt	(revision 5781)
@@ -18,5 +18,5 @@
         <div tal:replace="structure rendered_main" />
         
-        <p>Instructions :</p>
+        <p tal:condition="not: maintenance_online">Instructions :</p>
         
         <ul tal:condition="not: maintenance_online">
Index: /WAeUP_SRP/trunk/skins/waeup_epayment/interswitch_cb.py
===================================================================
--- /WAeUP_SRP/trunk/skins/waeup_epayment/interswitch_cb.py	(revision 5780)
+++ /WAeUP_SRP/trunk/skins/waeup_epayment/interswitch_cb.py	(revision 5781)
@@ -46,5 +46,7 @@
 logger.info('%s, callback referer = %s, IP = %s' % (student_id,referer,real_ip))
 
-if not 'webpay.interswitchng.com' in referer and not 'waeup.org' in referer:
+ontest = False
+
+if not ontest and not 'webpay.interswitchng.com' in referer and not 'waeup.org' in referer:
     logger.info('%s, wrong callback referer %s, callback rejected, IP = %s' % (student_id,referer,real_ip))
     return request.RESPONSE.redirect("%s/waeup_document_view" % context.absolute_url())
@@ -63,10 +65,10 @@
     pd[pdk] = request.get(rc,'')
 
-## for testing purposes
-#pd['resp_desc'] = 'Simulated Callback'
-#pd['resp_pay_reference'] = 'XXXX'
-#pd['resp_code'] = '00'
-#pd['resp_card_num'] = '0000'
-#pd['resp_approved_amount'] = '4680000'
+if ontest:
+    pd['resp_desc'] = 'Simulated Callback'
+    pd['resp_pay_reference'] = 'XXXX'
+    pd['resp_code'] = '00'
+    pd['resp_card_num'] = '0000'
+    pd['resp_approved_amount'] = '4680000'
 
 if pd['resp_code'] == '00' and len(pd['resp_approved_amount']) > 4:
@@ -92,5 +94,5 @@
         resp_approved_amount = int(pd['resp_approved_amount'])
         #set_trace()
-        if amount + surcharge != resp_approved_amount:
+        if not ontest and amount + surcharge != resp_approved_amount:
             logger.info('Warning: %s, approved amount %s and authorized amount %s are different for payment %s of %s' % (member,resp_approved_amount,amount+surcharge,context.getId(),student_id))
             pd['status'] = 'failed'
@@ -140,18 +142,28 @@
 
     elif pay_doc.category == 'hostel_maintenance':
-        acco_info = context.getAccommodationInfo()
-        d = {}
-        d['acco_maint_date'] = pay_doc.date
-        d['acco_maint_fee'] = pay_doc.amount
-        d['acco_maint_pay_id'] = context.getId()
-        try:
-            acco_info['acco_doc'].edit(mapping=d)
-        except:
-            logger.info('%s requeried payment though maintenance already paid' % student_id)
-
-        try:
-            wftool.doActionFor(acco_info['acco'],'pay_maintenance_fee',dest_container=acco_info['acco'])
-        except:
-            logger.info('%s no workflow action pay_maintenance_fee' % student_id)
+        
+        ## callback function for accommodation_catalog method
+        data={}
+        data['acco_maint_date'] = pay_doc.date
+        data['catkey'] =student_id + '|' + session
+        data['acco_maint_fee'] = pay_doc.amount
+        data['acco_maint_pay_id'] = context.getId()
+        data['reservation_status'] = 'maintenance_fee_paid'
+        context.accommodation_catalog.modifyRecord(**data)        
+        
+        ## callback function for accommodation object method (deactivated since March 2011)
+        #acco_info = context.getAccommodationInfo()
+        #d = {}
+        #d['acco_maint_date'] = pay_doc.date
+        #d['acco_maint_fee'] = pay_doc.amount
+        #d['acco_maint_pay_id'] = context.getId()
+        #try:
+        #    acco_info['acco_doc'].edit(mapping=d)
+        #except:
+        #    logger.info('%s requeried payment though maintenance already paid' % student_id)
+        #try:
+        #    wftool.doActionFor(acco_info['acco'],'pay_maintenance_fee',dest_container=acco_info['acco'])
+        #except:
+        #    logger.info('%s no workflow action pay_maintenance_fee' % student_id)
             
 
Index: /WAeUP_SRP/trunk/skins/waeup_fceokene/book_accommodation.py
===================================================================
--- /WAeUP_SRP/trunk/skins/waeup_fceokene/book_accommodation.py	(revision 5781)
+++ /WAeUP_SRP/trunk/skins/waeup_fceokene/book_accommodation.py	(revision 5781)
@@ -0,0 +1,112 @@
+## Script (Python) "book_accommodation.py"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=REQUEST
+# $Id$
+"""
+process the the accommodation reservation
+"""
+try:
+    from Products.zdb import set_trace
+except:
+    def set_trace():
+        pass
+import DateTime
+current = DateTime.DateTime()
+pr = context.portal_registration
+wftool = context.portal_workflow
+lt = context.portal_layouts
+info = context.getAccommodationStatus()
+
+import logging
+logger = logging.getLogger('Skins.book_accommodation')
+
+if info is None:
+    member_id = str(context.portal_membership.getAuthenticatedMember())
+    logger.info('%s tried to reserve accommodation' % (member_id))
+    return context.REQUEST.RESPONSE.redirect("%s/srp_invalid_access" % context.portal_url())
+
+if info['booking_disabled']:
+    return context.REQUEST.RESPONSE.redirect("%s/booking_disabled" % info['student'].absolute_url())
+if not info['booking_allowed']:
+    return context.REQUEST.RESPONSE.redirect("%s/no_booking_allowed" % info['student'].absolute_url())
+student = info['student']
+student_id = info['student_id']
+acco_id = info['acco_id']
+session = info['session'][0]
+mode = 'create'
+validate = REQUEST.has_key("cpsdocument_create_button")
+button = 'Book'
+
+res,psm,ds = lt.renderLayout(layout_id= 'student_accommodation_fe',
+                      schema_id= 'student_accommodation',
+                      context=context,
+                      mapping=validate and REQUEST,
+                      ob=info,
+                      layout_mode=mode,
+                      formaction = "book_accommodation",
+                      button = button)
+
+
+
+if psm == 'invalid':
+    member_id = str(context.portal_membership.getAuthenticatedMember())
+    #logger.info('%s, %s' % (member_id,info['error'] ))
+    logger.info('%s entered invalid data' % (member_id))
+    psm = "Please correct your input."
+    return context.book_accommodation_form(rendered = res,
+                                 psm = psm,
+                                 mode = mode,
+                                 ds = ds,
+                                 )
+elif psm == '':
+    return context.book_accommodation_form(rendered = res,
+                                 psm = None,
+                                 mode = mode,
+                                 ds = ds,
+                                 )
+elif psm == 'valid':
+    pin = str(ds.get('acco_res_sc_pin'))
+    code,bed = context.portal_accommodation.searchAndReserveBed(student_id,
+                                                                "%s" % (info['student_status']),
+                                                                random_order=True)
+    while True:
+        if code == 1:
+            break
+        if code == -1:
+            break
+        elif code == -2:
+            return context.book_accommodation_form(rendered = res,
+                                    psm = "No bed available. Your category is already fully booked.",
+                                    mode = mode,
+                                    ds = ds,
+                                    )
+        else: # unknown error
+            return context.book_accommodation_form(rendered = res,
+                                    psm = "Unexpected Error!",
+                                    mode = mode,
+                                    ds = ds,
+                                    )
+
+
+hall_info = context.waeup_tool.getHallInfo(bed)
+data={}
+data['acco_res_sc_pin'] = ds['acco_res_sc_pin']
+data['acco_maint_code'] = hall_info.get('maintenance_code')
+data['acco_maint_fee'] = hall_info.get('maintenance_fee')
+data['acco_res_date'] = current
+data['bed'] = bed
+data['session'] = session
+data['student_status'] = info['student_status']
+data['catkey'] =student_id + '|' + session
+data['student_id'] = student_id
+data['reservation_status'] = 'bed_reserved'
+
+#set_trace()
+context.accommodation_catalog.addRecord(**data)
+
+return context.REQUEST.RESPONSE.redirect("%s/accommodations" % student.absolute_url())
+
Index: /WAeUP_SRP/trunk/skins/waeup_futminna/accommodation_record_slip.pt
===================================================================
--- /WAeUP_SRP/trunk/skins/waeup_futminna/accommodation_record_slip.pt	(revision 5781)
+++ /WAeUP_SRP/trunk/skins/waeup_futminna/accommodation_record_slip.pt	(revision 5781)
@@ -0,0 +1,100 @@
+<metal:body use-macro="here/slip_template/macros/master">
+    <metal:main fill-slot="main"
+                tal:define="
+                            info_acco options/info|nothing;
+                            info_app context/getApplicationInfo;
+                            ">
+      <span tal:condition="python: not info_acco">
+            <span tal:content="here/illegal_view" />
+      </span>   
+      <span tal:condition="python: info_acco">                   
+          <h3>Hostel Allocation Slip (including Maintenance Receipt)</h3>
+
+          <br />
+           
+        <span tal:omit-tag=""
+              tal:content="structure python: info_app['app_doc'].render(proxy=info_app['app_doc'],
+              layout_mode='view_info', 
+              layout_id='student_application')" 
+              />     
+          
+       <table width="" cellpadding="2" cellspacing="0" summary="Form layout">
+
+         <tr>
+             <td width="180px" valign="top">
+              <span class="dlabel">Booking Session</span>:
+             </td>
+             <td> 
+                <span tal:content="python:context.portal_vocabularies.sessions.get(info_acco['Booking Session'])"></span>
+             </td>
+         </tr>
+         <tr>
+             <td width="180px" valign="top">
+              <span class="dlabel">Bed</span>:
+             </td>
+             <td> 
+                <span tal:content="python:context.getFormattedBed(info_acco['Bed'])"></span>
+             </td>
+         </tr>
+         <tr>
+             <td width="180px" valign="top">
+              <span class="dlabel">Bed Type</span>:
+             </td>
+             <td> 
+                <span tal:content="python:info_acco['Bed Type']"></span>
+             </td>
+         </tr>                  
+         <tr>
+             <td width="180px" valign="top">
+              <span class="dlabel">Hostel Application Date</span>:
+             </td>
+             <td> 
+                <span tal:content="python:context.getDateStr(fmt='%d/%m/%Y', dt=info_acco['Hostel Application Date'])"></span>
+             </td>
+         </tr>    
+
+         <tr>
+             <td width="180px" valign="top">
+              <span class="dlabel">Maintenance Payment Code</span>:
+             </td>
+             <td> 
+                <span tal:content="python:info_acco['Maintenance Payment Code']"></span>
+             </td>
+         </tr> 
+         <tr>
+             <td width="180px" valign="top">
+              <span class="dlabel">Maintenance Fee</span>:
+             </td>
+             <td> 
+                <span tal:content="python:info_acco['Maintenance Fee']"></span>
+             </td>
+         </tr>                     
+            
+         <tr>
+             <td width="180px" valign="top">
+              <span class="dlabel">Online Payment Id</span>:
+             </td>
+             <td> 
+                <span tal:content="python:info_acco['Online Payment Id']"></span>
+             </td>
+         </tr>            
+         <tr>
+             <td width="180px" valign="top">
+              <span class="dlabel">Maintenance Payment Date</span>:
+             </td>
+             <td> 
+                <span tal:content="python:context.getDateStr(fmt='%d/%m/%Y', dt=info_acco['Maintenance Payment Date'])"></span>
+             </td>
+         </tr>                                              
+         <tr>
+             <td width="180px" valign="top">
+              <span class="dlabel">Booking Status</span>:
+             </td>
+             <td> 
+                <span tal:content="python:info_acco['Booking Status']"></span>
+             </td>
+         </tr>
+       </table>
+      </span>      
+    </metal:main>
+</metal:body>
Index: /WAeUP_SRP/trunk/skins/waeup_futminna/getAccommodationStatus.py
===================================================================
--- /WAeUP_SRP/trunk/skins/waeup_futminna/getAccommodationStatus.py	(revision 5781)
+++ /WAeUP_SRP/trunk/skins/waeup_futminna/getAccommodationStatus.py	(revision 5781)
@@ -0,0 +1,136 @@
+## Script (Python) "getAccommodationStatus"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=student_id=None
+##title=
+##
+# $Id$
+"""
+return Info about the current Student
+"""
+try:
+    from Products.zdb import set_trace
+except:
+    def set_trace():
+        pass
+
+import logging
+logger = logging.getLogger('Skins.getAccommodationStatus')
+import DateTime
+
+pprops = context.portal_properties
+booking_disabled = not pprops.enable_acco_booking
+
+request = context.REQUEST
+mtool = context.portal_membership
+wf = context.portal_workflow
+member = mtool.getAuthenticatedMember()
+member_id = str(member)
+path_info = request.get('PATH_INFO').split('/')
+
+if mtool.isAnonymousUser():
+    return None
+info = {}
+if student_id is None:
+    requested_id = context.getStudentId()
+    if requested_id and not context.isStaff() and member_id != requested_id:
+        logger.info('%s tried to access %s' % (member_id,requested_id))
+        return None
+    elif context.isStaff():
+        student_id = requested_id
+    else:
+        student_id = member_id
+student_record = context.students_catalog.getRecordByKey(student_id)
+if student_record is None:
+    logger.info('%s not found in students_catalog' % student_id)
+    return None
+
+info['error'] = None
+info['matric_no']=student_record.matric_no
+info['jamb_reg_no']=student_record.jamb_reg_no
+info['name']=student_record.name
+info['email']=student_record.email
+info['level']=student_record.level
+info['verdict']=getattr(student_record,'verdict','')
+review_state = info['review_state'] = student_record.review_state
+info['session'] = session = context.getSessionId()
+students_object = context.portal_url.getPortalObject().campus.students
+student = getattr(students_object, student_id)
+info['student_id'] = student_id
+info['student'] = student
+
+# do not change these settings!
+
+booking_allowed = False
+info['booking_disabled'] = False
+
+# customize from here
+
+try:
+    level = int(student_record.level)
+except:
+    logger.info('%s has invalid level %s' % (student_id,student_record.level))
+    info['acco'] = None
+    info['booking_allowed'] = False
+    info['student_status'] = ''
+    return info    
+
+if review_state in ('cleared_and_validated','school_fee_paid','courses_registered', 'courses_validated',) and student_record.session == session[0]:
+    info['booking_allowed'] = True
+    info['online_payment'] = True
+# returning student can also book without having paid the school fee (see ticket #29)
+#elif review_state == 'returning' and int(student_record.session)+1 == int(session[0]):
+#    info['booking_allowed'] = True
+#    info['online_payment'] = True
+else:
+    info['acco'] = None
+    info['booking_allowed'] = False
+    info['student_status'] = ''
+    logger.info('%s: not eligible' % (student_id)) 
+    return info
+
+d = {}
+d['sex'] = 'male'
+#d['bt'] = 'all'
+if student_record.sex:
+    d['sex'] = 'female'
+    
+if level == 100:
+    bt = 'fr'
+else:
+    bt = 're'    
+if student_record.faculty in ('SSE'):
+    bt += "_sse"    
+d['bt'] = bt    
+
+info['sex']=d['sex']
+student_status = "%(sex)s_%(bt)s" % d
+info['student_status'] = student_status
+
+# customize end
+
+acco_id = student_id + '|' + session[0]
+info['acco_id'] = acco_id
+
+if booking_disabled:
+  info['booking_disabled'] = True
+  #logger.info('%s: %s eligible but booking disabled' % (student_id,student_status))  
+
+accommodation_record = context.accommodation_catalog.getRecordByKey(acco_id)
+if accommodation_record is None:
+    return info
+  
+info['booking_allowed'] = False
+info['acco_res_date'] = accommodation_record.acco_res_date
+info['acco_res_sc_pin'] = accommodation_record.acco_res_sc_pin
+info['acco_maint_fee'] = accommodation_record.acco_maint_fee
+info['acco_maint_code'] = accommodation_record.acco_maint_code
+info['student_status'] = accommodation_record.student_status
+info['bed'] = accommodation_record.bed
+info['session'] = accommodation_record.session
+info['maintenance_paid'] = accommodation_record.reservation_status == 'maintenance_fee_paid'
+
+return info
