Index: main/waeup.sirp/trunk/src/waeup/sirp/hostels/browser.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/hostels/browser.py	(revision 7058)
+++ main/waeup.sirp/trunk/src/waeup/sirp/hostels/browser.py	(revision 7068)
@@ -35,6 +35,8 @@
 from waeup.sirp.authentication import get_principal_role_manager
 from waeup.sirp.hostels.container import HostelsContainer
-from waeup.sirp.hostels.hostel import Hostel, NOT_OCCUPIED
-from waeup.sirp.hostels.interfaces import IHostelsContainer, IHostel
+from waeup.sirp.hostels.vocabularies import NOT_OCCUPIED
+from waeup.sirp.hostels.hostel import Hostel
+from waeup.sirp.hostels.interfaces import (
+    IHostelsContainer, IHostel, IBed, IBedAllocateStudent)
 
 def write_log_message(view, message):
@@ -86,4 +88,13 @@
     def title(self):
         return self.context.hostel_name
+
+class BedBreadcrumb(Breadcrumb):
+    """A breadcrumb for the hostel container.
+    """
+    grok.context(IBed)
+
+    def title(self):
+        co = self.context.getBedCoordinates()
+        return 'Block %s, Room %s, Bed %s' % (co[1], co[2], co[3])
 
 class HostelsContainerPage(WAeUPDisplayFormPage):
@@ -277,12 +288,6 @@
         released = []
         for bed_id in child_id:
-            try:
-                message = self.context[bed_id].releaseBed()
-                released.append('%s (%s)' % (bed_id,message))
-            except:
-                self.flash('Could not release %s: %s: %s' % (
-                        id, sys.exc_info()[0], sys.exc_info()[1]))
-                self.redirect(self.url(self.context, '@@manage')+'#tab-2')
-                return
+            message = self.context[bed_id].releaseBed()
+            released.append('%s (%s)' % (bed_id,message))
         if len(released):
             message = ', '.join(released)
@@ -291,2 +296,33 @@
             self.redirect(self.url(self.context, '@@manage')+'#tab-2')
         return
+
+class BedManageFormPage(WAeUPEditFormPage):
+    """ View to edit bed data
+    """
+    grok.context(IBedAllocateStudent)
+    grok.name('index')
+    grok.require('waeup.manageHostels')
+    form_fields = grok.AutoFields(IBedAllocateStudent).omit(
+        'bed_id').omit('bed_number').omit('bed_type')
+    label = 'Allocate student'
+    pnav = 5
+
+    @property
+    def title(self):
+        co = self.context.getBedCoordinates()
+        return '%s, Block %s, Room %s, Bed %s' % (
+            self.context.__parent__.hostel_name, co[1], co[2], co[3])
+
+    @grok.action('Save')
+    def save(self, **data):
+        msave(self, **data)
+        self.redirect(self.url(self.context.__parent__, '@@manage')+'#tab-2')
+        return
+
+    def update(self):
+        if self.context.owner != NOT_OCCUPIED:
+            # Don't use this form for exchanging students.
+            # Beds must be released first before they can be allocated to
+            # other students.
+            self.redirect(self.url(self.context.__parent__, '@@manage')+'#tab-2')
+        return
Index: main/waeup.sirp/trunk/src/waeup/sirp/hostels/browser_templates/hostelmanagepage.pt
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/hostels/browser_templates/hostelmanagepage.pt	(revision 7058)
+++ main/waeup.sirp/trunk/src/waeup/sirp/hostels/browser_templates/hostelmanagepage.pt	(revision 7068)
@@ -88,4 +88,8 @@
               <span tal:content="value/owner">Owner</span>
             </a>
+            <a tal:condition="python: value.owner == view.not_occupied"
+               tal:attributes="href python: view.url(value)">
+            [allocate student]
+            </a>
           </td>
         </tr>
Index: main/waeup.sirp/trunk/src/waeup/sirp/hostels/catalog.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/hostels/catalog.py	(revision 7058)
+++ main/waeup.sirp/trunk/src/waeup/sirp/hostels/catalog.py	(revision 7068)
@@ -21,15 +21,2 @@
     bed_type = index.Field(attribute='bed_type')
     owner = index.Field(attribute='owner')
-
-class BedQueryResultItem(object):
-    grok.implements(IQueryResultItem)
-
-    title = u'Bed Query Item'
-    description = u'Some bed found in a search'
-
-    def __init__(self, context, view):
-        self.context = context
-        self.url = view.url(context)
-        self.bed_id = context.bed_id
-        self.bed_type = context.bed_type
-        self.bed_number = context.bed_number
Index: main/waeup.sirp/trunk/src/waeup/sirp/hostels/hostel.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/hostels/hostel.py	(revision 7058)
+++ main/waeup.sirp/trunk/src/waeup/sirp/hostels/hostel.py	(revision 7068)
@@ -22,8 +22,7 @@
 from grok import index
 from waeup.sirp.utils.helpers import attrs_to_fields
-from waeup.sirp.hostels.interfaces import IHostel, IBed
+from waeup.sirp.hostels.vocabularies import NOT_OCCUPIED
+from waeup.sirp.hostels.interfaces import IHostel, IBed, IBedAllocateStudent
 from waeup.sirp.students.interfaces import IBedTicket
-
-NOT_OCCUPIED = u'not occupied'
 
 class Hostel(grok.Container):
@@ -121,5 +120,5 @@
     """This is a bed.
     """
-    grok.implements(IBed)
+    grok.implements(IBed, IBedAllocateStudent)
     grok.provides(IBed)
 
@@ -208,5 +207,5 @@
     of the bed is cleared (set to NOT_OCCUPIED).
     """
-    allocated_bed = bedticket.bed
-    allocated_bed.owner = NOT_OCCUPIED
-    notify(grok.ObjectModifiedEvent(allocated_bed))
+    if bedticket.bed != None:
+        bedticket.bed.owner = NOT_OCCUPIED
+        notify(grok.ObjectModifiedEvent(bedticket.bed))
Index: main/waeup.sirp/trunk/src/waeup/sirp/hostels/interfaces.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/hostels/interfaces.py	(revision 7058)
+++ main/waeup.sirp/trunk/src/waeup/sirp/hostels/interfaces.py	(revision 7068)
@@ -5,5 +5,5 @@
 from waeup.sirp.interfaces import IWAeUPObject
 from waeup.sirp.hostels.vocabularies import (
-    bed_letters, blocks, special_handling)
+    bed_letters, blocks, special_handling, StudentSource)
 
 class IHostelsContainer(IWAeUPObject):
@@ -172,2 +172,16 @@
         default = u'',
         )
+
+
+
+class IBedAllocateStudent(IBed):
+    """A representation of beds for allocation form only.
+
+    """
+
+    owner = schema.Choice(
+        title = u'Owner (Student)',
+        source = StudentSource(),
+        default = None,
+        required = True,
+        )
Index: main/waeup.sirp/trunk/src/waeup/sirp/hostels/tests.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/hostels/tests.py	(revision 7058)
+++ main/waeup.sirp/trunk/src/waeup/sirp/hostels/tests.py	(revision 7068)
@@ -108,4 +108,7 @@
         self.student['studycourse'].current_session = 2004
         self.student['studycourse'].entry_session = 2004
+        # The students_catalog must be informed that the
+        # session attribute has changed
+        notify(grok.ObjectModifiedEvent(self.student))
 
         # Set accommodation_session
@@ -125,4 +128,5 @@
 
         self.container_path = 'http://localhost/app/hostels'
+        self.student_path = 'http://localhost/app/students/%s' % self.student_id
         self.manage_container_path = self.container_path + '/@@manage'
         self.add_hostel_path = self.container_path + '/addhostel'
@@ -269,4 +273,7 @@
         self.browser.open(self.container_path + '/hall-1/manage')
         ctrl = self.browser.getControl(name='val_id')
+        self.browser.getControl("Release selected beds", index=0).click()
+        self.assertMatches("...No item selected...", self.browser.contents)
+        ctrl = self.browser.getControl(name='val_id')
         ctrl.getControl(value='hall-1_A_101_D').selected = True
         self.browser.getControl("Release selected beds", index=0).click()
@@ -276,4 +283,9 @@
         self.assertMatches(bedticket.bed_coordinates,
           u' -- booking cancelled on <YYYY-MM-DD hh:mm:ss> --')
+        # Managers can manually allocate studenst after cancellation
+        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_A')
+        self.browser.getControl(name="form.owner").value = [self.student_id]
+        self.browser.getControl("Save").click()
+        self.assertMatches("...Form has been saved...", self.browser.contents)
         # Remove entire hostel
         self.browser.open(self.manage_container_path)
Index: main/waeup.sirp/trunk/src/waeup/sirp/hostels/vocabularies.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/hostels/vocabularies.py	(revision 7058)
+++ main/waeup.sirp/trunk/src/waeup/sirp/hostels/vocabularies.py	(revision 7068)
@@ -1,7 +1,42 @@
 """Vocabularies and sources for the accommodation section.
 """
+from  grok import getSite
+from zope.component import getUtility
+from zope.catalog.interfaces import ICatalog
+from zc.sourcefactory.contextual import BasicContextualSourceFactory
 from zc.sourcefactory.basic import BasicSourceFactory
 from waeup.sirp.interfaces import SimpleWAeUPVocabulary
 
+NOT_OCCUPIED = u'not occupied'
+
+class StudentSource(BasicContextualSourceFactory):
+    """A students source delivers all students in accommodation session.
+    """
+
+    def acco_students(self, context):
+        catalog = getUtility(ICatalog, name='students_catalog')
+        accommodation_session = getSite()['configuration'].accommodation_session
+        students = catalog.searchResults(current_session=(
+            accommodation_session,accommodation_session))
+        try:
+            existing_students = [
+                context.__parent__[key].owner
+                for key in context.__parent__.keys()]
+        except AttributeError:
+            return {NOT_OCCUPIED:NOT_OCCUPIED}
+        students = [student for student in students
+                      if not student.student_id in existing_students]
+        students = sorted(list(students),
+                          key=lambda value: value.student_id)
+        return dict([(student.student_id,student.fullname) for student in students])
+
+    def getValues(self, context):
+        return self.acco_students(context).keys()
+
+    def getToken(self, context, value):
+        return value
+
+    def getTitle(self, context, value):
+        return "%s - %s" % (value, self.acco_students(context)[value])
 
 bed_letters = SimpleWAeUPVocabulary(
