Index: main/waeup.uniben/trunk/src/waeup/uniben/students/tests/test_browser.py
===================================================================
--- main/waeup.uniben/trunk/src/waeup/uniben/students/tests/test_browser.py	(revision 13110)
+++ main/waeup.uniben/trunk/src/waeup/uniben/students/tests/test_browser.py	(revision 13251)
@@ -19,7 +19,10 @@
 import shutil
 import tempfile
+import pytz
+from datetime import datetime, timedelta, date
 from StringIO import StringIO
 from hurry.workflow.interfaces import IWorkflowState, IWorkflowInfo
 from zope.securitypolicy.interfaces import IPrincipalRoleManager
+from zope.security.interfaces import Unauthorized
 from zope.component.hooks import setSite, clearSite
 from zope.component import getUtility, createObject
@@ -30,4 +33,5 @@
 from waeup.kofa.students.tests.test_browser import StudentsFullSetup
 from waeup.kofa.students.accommodation import BedTicket
+from waeup.kofa.hostels.hostel import Hostel, Bed, NOT_OCCUPIED
 from waeup.kofa.testing import FunctionalTestCase
 from waeup.kofa.browser.tests.test_pdf import samples_dir
@@ -47,11 +51,4 @@
     def setUp(self):
         super(StudentUITests, self).setUp()
-
-        bedticket = BedTicket()
-        bedticket.booking_session = 2004
-        bedticket.bed_type = u'any bed type'
-        bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
-        bedticket.bed_coordinates = u'My bed coordinates'
-        self.student['accommodation'].addBedTicket(bedticket)
 
     def test_next_session_allowed(self):
@@ -253,35 +250,35 @@
                            self.browser.contents)
         self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl(
-            name="form.p_category").value = ['tempmaint_1']
-        self.browser.getControl("Create ticket").click()
-        self.assertMatches('...You have not yet paid the hostel application fee...',
-                           self.browser.contents)
-        self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl(name="form.p_category").value = ['hostel_application']
-        self.browser.getControl("Create ticket").click()
-        self.assertMatches('...ticket created...',
-                           self.browser.contents)
-        ha_ticket = self.student['payments'].values()[2]
-        ha_ticket.approve()
-        self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl(
-            name="form.p_category").value = ['tempmaint_1']
-        self.browser.getControl("Create ticket").click()
-        self.assertMatches('...ticket created...',
-                           self.browser.contents)
-        self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl(
-            name="form.p_category").value = ['tempmaint_2']
-        self.browser.getControl("Create ticket").click()
-        self.assertMatches('...ticket created...',
-                           self.browser.contents)
-        self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl(
-            name="form.p_category").value = ['tempmaint_3']
-        self.browser.getControl("Create ticket").click()
-        self.assertMatches('...ticket created...',
-                           self.browser.contents)
-        self.browser.open(self.payments_path + '/addop')
+        #self.browser.getControl(
+        #    name="form.p_category").value = ['tempmaint_1']
+        #self.browser.getControl("Create ticket").click()
+        #self.assertMatches('...You have not yet paid the hostel application fee...',
+        #                   self.browser.contents)
+        #self.browser.open(self.payments_path + '/addop')
+        #self.browser.getControl(name="form.p_category").value = ['hostel_application']
+        #self.browser.getControl("Create ticket").click()
+        #self.assertMatches('...ticket created...',
+        #                   self.browser.contents)
+        #ha_ticket = self.student['payments'].values()[2]
+        #ha_ticket.approve()
+        #self.browser.open(self.payments_path + '/addop')
+        #self.browser.getControl(
+        #    name="form.p_category").value = ['tempmaint_1']
+        #self.browser.getControl("Create ticket").click()
+        #self.assertMatches('...ticket created...',
+        #                   self.browser.contents)
+        #self.browser.open(self.payments_path + '/addop')
+        #self.browser.getControl(
+        #    name="form.p_category").value = ['tempmaint_2']
+        #self.browser.getControl("Create ticket").click()
+        #self.assertMatches('...ticket created...',
+        #                   self.browser.contents)
+        #self.browser.open(self.payments_path + '/addop')
+        #self.browser.getControl(
+        #    name="form.p_category").value = ['tempmaint_3']
+        #self.browser.getControl("Create ticket").click()
+        #self.assertMatches('...ticket created...',
+        #                   self.browser.contents)
+        #self.browser.open(self.payments_path + '/addop')
         # We can't test clearance payment ticket creation at the moment,
         # since Uniben decided to deactivate clearance for ug students.
@@ -604,54 +601,61 @@
         self.assertEqual(error, None)
 
-        #error, payment = utils.setPaymentDetails('hostel_maintenance',
+        bedticket = BedTicket()
+        bedticket.booking_session = 2004
+        bedticket.bed_type = u'any bed type'
+        bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
+        bedticket.bed_coordinates = u'My bed coordinates'
+        self.student['accommodation'].addBedTicket(bedticket)
+
+        error, payment = utils.setPaymentDetails('hostel_maintenance',
+            self.student, None, None)
+        self.assertEqual(payment.p_level, 100)
+        self.assertEqual(payment.p_session, 2004)
+        self.assertEqual(payment.amount_auth, 876.0)
+        self.assertEqual(payment.p_item, u'My bed coordinates')
+        self.assertEqual(error, None)
+
+        error, payment = utils.setPaymentDetails('bed_allocation',
+            self.student, None, None)
+        self.assertEqual(payment.p_level, 100)
+        self.assertEqual(payment.p_session, 2004)
+        self.assertEqual(payment.amount_auth, 150.0)
+        self.assertEqual(payment.p_item, u'regular_male_re')
+        self.assertEqual(error, None)
+
+        #error, payment = utils.setPaymentDetails('hostel_application',
         #    self.student, None, None)
         #self.assertEqual(payment.p_level, 100)
         #self.assertEqual(payment.p_session, 2004)
-        #self.assertEqual(payment.amount_auth, 180.0)
+        #self.assertEqual(payment.amount_auth, 1000.0)
         #self.assertEqual(payment.p_item, u'')
         #self.assertEqual(error, None)
 
-        #error, payment = utils.setPaymentDetails('bed_allocation',
+        #payment.approve()
+        #self.student['payments'][payment.p_id] = payment
+
+        #error, payment = utils.setPaymentDetails('tempmaint_1',
         #    self.student, None, None)
         #self.assertEqual(payment.p_level, 100)
         #self.assertEqual(payment.p_session, 2004)
-        #self.assertEqual(payment.amount_auth, 150.0)
-        #self.assertEqual(payment.p_item, u'')
+        #self.assertEqual(payment.amount_auth, 8150.0)
+        #self.assertEqual(payment.p_item, u'Hall 1-4 M/F Ekehuan')
         #self.assertEqual(error, None)
 
-        error, payment = utils.setPaymentDetails('hostel_application',
-            self.student, None, None)
-        self.assertEqual(payment.p_level, 100)
-        self.assertEqual(payment.p_session, 2004)
-        self.assertEqual(payment.amount_auth, 1000.0)
-        self.assertEqual(payment.p_item, u'')
-        self.assertEqual(error, None)
-
-        payment.approve()
-        self.student['payments'][payment.p_id] = payment
-
-        error, payment = utils.setPaymentDetails('tempmaint_1',
-            self.student, None, None)
-        self.assertEqual(payment.p_level, 100)
-        self.assertEqual(payment.p_session, 2004)
-        self.assertEqual(payment.amount_auth, 8150.0)
-        self.assertEqual(payment.p_item, u'Hall 1-4 M/F Ekehuan')
-        self.assertEqual(error, None)
-
-        error, payment = utils.setPaymentDetails('tempmaint_2',
-            self.student, None, None)
-        self.assertEqual(payment.p_level, 100)
-        self.assertEqual(payment.p_session, 2004)
-        self.assertEqual(payment.amount_auth, 12650.0)
-        self.assertEqual(payment.p_item, u'Hall 5 M/F')
-        self.assertEqual(error, None)
-
-        error, payment = utils.setPaymentDetails('tempmaint_3',
-            self.student, None, None)
-        self.assertEqual(payment.p_level, 100)
-        self.assertEqual(payment.p_session, 2004)
-        self.assertEqual(payment.amount_auth, 9650.0)
-        self.assertEqual(payment.p_item, u'Clinical Hostel')
-        self.assertEqual(error, None)
+        #error, payment = utils.setPaymentDetails('tempmaint_2',
+        #    self.student, None, None)
+        #self.assertEqual(payment.p_level, 100)
+        #self.assertEqual(payment.p_session, 2004)
+        #self.assertEqual(payment.amount_auth, 12650.0)
+        #self.assertEqual(payment.p_item, u'Hall 5 M/F')
+        #self.assertEqual(error, None)
+
+        #error, payment = utils.setPaymentDetails('tempmaint_3',
+        #    self.student, None, None)
+        #self.assertEqual(payment.p_level, 100)
+        #self.assertEqual(payment.p_session, 2004)
+        #self.assertEqual(payment.amount_auth, 9650.0)
+        #self.assertEqual(payment.p_item, u'Clinical Hostel')
+        #self.assertEqual(error, None)
 
         error, payment = utils.setPaymentDetails('transfer',
@@ -901,2 +905,116 @@
         open(path, 'wb').write(self.browser.contents)
         print "Sample PDF transcript.pdf written to %s" % path
+
+    def test_student_accommodation(self):
+        self.browser.open(self.login_path)
+        self.browser.getControl(name="form.login").value = self.student_id
+        self.browser.getControl(name="form.password").value = 'spwd'
+        self.browser.getControl("Login").click()
+        # Students can add online booking fee payment tickets and open the
+        # callback view (see test_manage_payments).
+        self.browser.getLink("Payments").click()
+        self.browser.getLink("Add current session payment ticket").click()
+        self.browser.getControl(name="form.p_category").value = ['bed_allocation']
+        self.browser.getControl("Create ticket").click()
+        ctrl = self.browser.getControl(name='val_id')
+        value = ctrl.options[0]
+        self.browser.getLink(value).click()
+        p_ticket = self.student['payments'].values()[0]
+        p_ticket.approveStudentPayment()
+        # The new HOS-0 pin has been created.
+        self.assertEqual(len(self.app['accesscodes']['HOS-0']),1)
+        pin = self.app['accesscodes']['HOS-0'].keys()[0]
+        ac = self.app['accesscodes']['HOS-0'][pin]
+        parts = pin.split('-')[1:]
+        sfeseries, sfenumber = parts
+        # Students can use HOS code and book a bed space with it ...
+        self.browser.open(self.acco_path)
+        # ... but not if booking period has expired ...
+        self.app['hostels'].enddate = datetime.now(pytz.utc)
+        self.browser.getLink("Book accommodation").click()
+        self.assertMatches('...Outside booking period: ...',
+                           self.browser.contents)
+        self.app['hostels'].enddate = datetime.now(pytz.utc) + timedelta(days=10)
+        # ... or student data are incomplete ...
+        self.student['studycourse'].current_level = None
+        self.browser.getLink("Book accommodation").click()
+        self.assertMatches('...Your data are incomplete...',
+            self.browser.contents)
+        self.student['studycourse'].current_level = 100
+        # ... or student is not the an allowed state ...
+        self.browser.getLink("Book accommodation").click()
+        self.assertMatches('...You are in the wrong...',
+                           self.browser.contents)
+        IWorkflowInfo(self.student).fireTransition('admit')
+        self.browser.getLink("Book accommodation").click()
+        self.assertMatches('...Activation Code:...',
+                           self.browser.contents)
+        # Student can't use faked ACs ...
+        self.browser.getControl(name="ac_series").value = u'nonsense'
+        self.browser.getControl(name="ac_number").value = sfenumber
+        self.browser.getControl("Create bed ticket").click()
+        self.assertMatches('...Activation code is invalid...',
+                           self.browser.contents)
+        # ... or ACs owned by somebody else.
+        ac.owner = u'Anybody'
+        self.browser.getControl(name="ac_series").value = sfeseries
+        self.browser.getControl(name="ac_number").value = sfenumber
+        self.browser.getControl("Create bed ticket").click()
+        self.assertMatches('...You are not the owner of this access code...',
+                           self.browser.contents)
+        # The bed remains empty.
+        bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
+        self.assertTrue(bed.owner == NOT_OCCUPIED)
+        ac.owner = self.student_id
+        self.browser.getControl(name="ac_series").value = sfeseries
+        self.browser.getControl(name="ac_number").value = sfenumber
+        self.browser.getControl("Create bed ticket").click()
+        self.assertMatches('...Hall 1, Block A, Room 101, Bed A...',
+                           self.browser.contents)
+        # Bed has been allocated.
+        self.assertTrue(bed.owner == self.student_id)
+        # BedTicketAddPage is now blocked.
+        self.browser.getLink("Book accommodation").click()
+        self.assertMatches('...You already booked a bed space...',
+            self.browser.contents)
+        # The bed ticket displays the data correctly.
+        self.browser.open(self.acco_path + '/2004')
+        self.assertMatches('...Hall 1, Block A, Room 101, Bed A...',
+                           self.browser.contents)
+        self.assertMatches('...2004/2005...', self.browser.contents)
+        self.assertMatches('...regular_male_fr...', self.browser.contents)
+        self.assertMatches('...%s...' % pin, self.browser.contents)
+        # Students can open the pdf slip.
+        self.browser.open(self.browser.url + '/bed_allocation_slip.pdf')
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
+        # Students can't relocate themselves.
+        self.assertFalse('Relocate' in self.browser.contents)
+        relocate_path = self.acco_path + '/2004/relocate'
+        self.assertRaises(
+            Unauthorized, self.browser.open, relocate_path)
+        # Students can't see the Remove button and check boxes.
+        self.browser.open(self.acco_path)
+        self.assertFalse('Remove' in self.browser.contents)
+        self.assertFalse('val_id' in self.browser.contents)
+        # Students can pay maintenance fee now.
+        self.browser.open(self.payments_path)
+        self.browser.open(self.payments_path + '/addop')
+        self.browser.getControl(name="form.p_category").value = ['hostel_maintenance']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...Payment ticket created...',
+                           self.browser.contents)
+        ctrl = self.browser.getControl(name='val_id')
+        value = ctrl.options[0]
+        # Maintennace fee is taken from the hostel object.
+        self.assertEqual(self.student['payments'][value].amount_auth, 876.0)
+        # If the hostel's maintenance fee isn't set, the fee is
+        # taken from the session configuration object.
+        self.app['hostels']['hall-1'].maint_fee = 0.0
+        self.browser.open(self.payments_path + '/addop')
+        self.browser.getControl(name="form.p_category").value = ['hostel_maintenance']
+        self.browser.getControl("Create ticket").click()
+        ctrl = self.browser.getControl(name='val_id')
+        value = ctrl.options[1]
+        self.assertEqual(self.student['payments'][value].amount_auth, 987.0)
+        return
