Index: main/waeup.kofa/trunk/src/waeup/kofa/students/accommodation.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/accommodation.py	(revision 9422)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/accommodation.py	(revision 9423)
@@ -30,5 +30,5 @@
 
 class StudentAccommodation(grok.Container):
-    """This is a container for accommodation objects.
+    """This is a container for bed tickets.
     """
     grok.implements(IStudentAccommodation, IStudentNavigation)
@@ -45,5 +45,5 @@
             raise TypeError(
                 'StudentAccommodation containers contain only IBedTicket instances')
-        self[bedticket.ticket_id] = bedticket
+        self[str(bedticket.booking_session)] = bedticket
         return
 
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py	(revision 9422)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py	(revision 9423)
@@ -1339,4 +1339,10 @@
                 self.redirect(self.url(self.context))
                 return
+        if 'maintenance' in p_category:
+            current_session = str(student['studycourse'].current_session)
+            if not student['accommodation'].has_key(current_session):
+                self.flash(_('You have not yet booked a bed.'))
+                self.redirect(self.url(self.context))
+                return
         students_utils = getUtility(IStudentsUtils)
         error, payment = students_utils.setPaymentDetails(
@@ -1627,6 +1633,5 @@
         bedticket.bed_coordinates = translate(
             bc, 'waeup.kofa',target_language=portal_language)
-        key = str(acc_details['booking_session'])
-        self.context[key] = bedticket
+        self.context.addBedTicket(bedticket)
         self.context.writeLogMessage(self, 'booked: %s' % bed.bed_id)
         self.flash(_('Bed ticket created and bed booked: ${a}',
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/interfaces.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/interfaces.py	(revision 9422)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/interfaces.py	(revision 9423)
@@ -590,4 +590,9 @@
     """
 
+    def addBedTicket(bedticket):
+        """Add a bed ticket object.
+        """
+
+
 class IBedTicket(IKofaObject):
     """A ticket for accommodation booking.
@@ -598,5 +603,5 @@
     bed_coordinates = schema.TextLine(
         title = _(u'Bed Coordinates'),
-        required = False,
+        required = True,
         readonly = False,
         )
@@ -604,5 +609,5 @@
     bed_type = schema.TextLine(
         title = _(u'Bed Type'),
-        required = False,
+        required = True,
         readonly = False,
         )
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py	(revision 9422)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py	(revision 9423)
@@ -186,4 +186,5 @@
         configuration.clearance_fee = 3456.0
         configuration.booking_fee = 123.4
+        configuration.maint_fee = 987.0
         self.app['configuration'].addSessionConfiguration(configuration)
 
@@ -1889,5 +1890,5 @@
                            self.browser.contents)
 
-    def test_student_payments(self):
+    def test_student_clearance_payment(self):
         # Login
         self.browser.open(self.login_path)
@@ -1965,7 +1966,16 @@
                            self.browser.contents)
 
+    def test_student_schoolfee_payment(self):
+        # Login
+        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 school fee payment tickets.
         IWorkflowState(self.student).setState('returning')
         self.browser.open(self.payments_path)
+        self.assertRaises(
+            LookupError, self.browser.getControl, name='val_id')
         self.browser.getControl("Add online payment ticket").click()
         self.browser.getControl(name="form.p_category").value = ['schoolfee']
@@ -1997,19 +2007,4 @@
         self.assertMatches('...Payment approved...',
                           self.browser.contents)
-
-        # Students can remove only online payment tickets which have
-        # not received a valid callback
-        self.browser.open(self.payments_path)
-        self.assertRaises(
-            LookupError, self.browser.getControl, name='val_id')
-        self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl(name="form.p_category").value = ['bed_allocation']
-        self.browser.getControl("Create ticket").click()
-        self.browser.open(self.payments_path)
-        ctrl = self.browser.getControl(name='val_id')
-        value = ctrl.options[0]
-        ctrl.getControl(value=value).selected = True
-        self.browser.getControl("Remove selected", index=0).click()
-        self.assertTrue('Successfully removed' in self.browser.contents)
 
         # The new SFE-0 pin can be used for starting new session
@@ -2026,4 +2021,39 @@
         self.assertTrue(self.student.state == 'school fee paid')
         return
+
+    def test_student_bedallocation_payment(self):
+        # Login
+        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()
+        self.browser.open(self.payments_path)
+        self.browser.open(self.payments_path + '/addop')
+        self.browser.getControl(name="form.p_category").value = ['bed_allocation']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...ticket created...',
+                           self.browser.contents)
+        # Students can remove only online payment tickets which have
+        # not received a valid callback
+        self.browser.open(self.payments_path)
+        ctrl = self.browser.getControl(name='val_id')
+        value = ctrl.options[0]
+        ctrl.getControl(value=value).selected = True
+        self.browser.getControl("Remove selected", index=0).click()
+        self.assertTrue('Successfully removed' in self.browser.contents)
+
+    def test_student_maintenance_payment(self):
+        # Login
+        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()
+        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('...You have not yet booked a bed...',
+                           self.browser.contents)
+        # We continue this test in test_student_accommodation
 
     def test_student_previous_payments(self):
@@ -2285,4 +2315,12 @@
         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)
         return
 
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py	(revision 9422)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py	(revision 9423)
@@ -360,4 +360,6 @@
             p_item = self.getAccommodationDetails(student)['bt']
             amount = academic_session.booking_fee
+        elif category == 'hostel_maintenance':
+            amount = academic_session.maint_fee
         if amount in (0.0, None):
             return _('Amount could not be determined.' +
