Index: main/waeup.sirp/trunk/src/waeup/sirp/applicants/browser.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/applicants/browser.py	(revision 7067)
+++ main/waeup.sirp/trunk/src/waeup/sirp/applicants/browser.py	(revision 7068)
@@ -650,5 +650,5 @@
         story.append(Spacer(1, 24))
 
-        data = []
+
         # insert passport photograph
         img = getUtility(IExtFileStore).getFileByContext(self.context)
@@ -656,7 +656,9 @@
             img = open(os.path.join(IMAGE_PATH, 'placeholder_m.jpg'), 'rb')
         doc_img = Image(img.name, width=4*cm, height=3*cm, kind='bound')
-        data.append(['', doc_img])
+        story.append(doc_img)
+        story.append(Spacer(1, 18))
 
         # render widget fields
+        data = []
         self.setUpWidgets()
         for widget in self.widgets:
Index: main/waeup.sirp/trunk/src/waeup/sirp/applicants/browser_templates/form_display.pt
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/applicants/browser_templates/form_display.pt	(revision 7067)
+++ main/waeup.sirp/trunk/src/waeup/sirp/applicants/browser_templates/form_display.pt	(revision 7068)
@@ -13,5 +13,5 @@
 <table class="zebra">
   <tbody>
-    <tr><td></td>
+    <tr>
     <td><img src="" tal:attributes="src view/passport_url" /></td>
     </tr>
Index: main/waeup.sirp/trunk/src/waeup/sirp/hostels/browser.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/hostels/browser.py	(revision 7067)
+++ 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 7067)
+++ 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 7067)
+++ 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 7067)
+++ 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 7067)
+++ 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 7067)
+++ 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 7067)
+++ 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(
Index: main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py	(revision 7067)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py	(revision 7068)
@@ -186,4 +186,6 @@
                 self.flash('Empty search string.')
             return
+        if self.searchtype == 'current_session':
+            self.searchterm = int(self.searchterm)
         self.hitlist = search(query=self.searchterm,
             searchtype=self.searchtype, view=self)
@@ -1178,10 +1180,6 @@
         deleted = []
         for id in child_id:
-            try:
-                del self.context[id]
-                deleted.append(id)
-            except:
-                self.flash('Could not delete %s: %s: %s' % (
-                        id, sys.exc_info()[0], sys.exc_info()[1]))
+            del self.context[id]
+            deleted.append(id)
         if len(deleted):
             self.flash('Successfully removed: %s' % ', '.join(deleted))
@@ -1295,6 +1293,6 @@
         coordinates = bed.getBedCoordinates()[1:]
         block, room_nr, bed_nr = coordinates
-        bedticket.bed_coordinates = '%s, Block %s, Room %s, Bed %s' % (
-            hall_title, block, room_nr, bed_nr)
+        bedticket.bed_coordinates = '%s, Block %s, Room %s, Bed %s (%s)' % (
+            hall_title, block, room_nr, bed_nr, bed.bed_type)
         key = str(acc_details['booking_session'])
         self.context[key] = bedticket
@@ -1381,45 +1379,55 @@
         student = self.context.getStudent()
         acc_details  = self.getAccommodationDetails(student)
+        if self.context.bed != None and \
+              'reserved' in self.context.bed.bed_type:
+            self.flash("Students in reserved beds can't be relocated.")
+            self.redirect(self.url(self.context))
+            return
         if acc_details['bt'] == self.context.bed_type and \
+                self.context.bed != None and \
                 self.context.bed.bed_type == self.context.bed_type:
-            self.flash("Bed category hasn't changed. Student can't be relocated.")
-            return
-        # Search a bed and exit if no bed is found
+            self.flash("Student can't be relocated.")
+            self.redirect(self.url(self.context))
+            return
+        # Search a bed
         cat = queryUtility(ICatalog, name='beds_catalog', default=None)
         entries = cat.searchResults(
-            bed_type=(acc_details['bt'],acc_details['bt']))
-        available_beds = [
-            entry for entry in entries if entry.owner == NOT_OCCUPIED]
-        if not available_beds:
-            self.flash('There is no free bed in your category %s.'
-                        % acc_details['bt'])
-            return
-        #entries = cat.searchResults(
-        #    owner=(student.student_id,student.student_id))
-        # Rlease old bed
-        try:
-            allocated_bed = self.context.bed
-            allocated_bed.owner = NOT_OCCUPIED
-            notify(grok.ObjectModifiedEvent(allocated_bed))
-        except AttributeError:
-            # Cannot happen but anyway...
-            pass
+            owner=(student.student_id,student.student_id))
+        if len(entries) and self.context.bed == None:
+            # If booking has been cancelled but other bed space has been
+            # manually allocated after cancellation use this bed
+            new_bed = [entry for entry in entries][0]
+        else:
+            # Search for other available beds
+            entries = cat.searchResults(
+                bed_type=(acc_details['bt'],acc_details['bt']))
+            available_beds = [
+                entry for entry in entries if entry.owner == NOT_OCCUPIED]
+            if available_beds:
+                new_bed = self.selectBed(available_beds)
+                new_bed.bookBed(student.student_id)
+            else:
+                self.flash('There is no free bed in your category %s.'
+                            % acc_details['bt'])
+                self.redirect(self.url(self.context))
+                return
+        # Rlease old bed if exists
+        if self.context.bed != None:
+            self.context.bed.owner = NOT_OCCUPIED
+            notify(grok.ObjectModifiedEvent(self.context.bed))
         # Alocate new bed
         self.context.bed_type = acc_details['bt']
-        bed = self.selectBed(available_beds)
-        bed.bookBed(student.student_id)
-        self.context.bed = bed
-        hall_title = bed.__parent__.hostel_name
-        coordinates = bed.getBedCoordinates()[1:]
+        self.context.bed = new_bed
+        hall_title = new_bed.__parent__.hostel_name
+        coordinates = new_bed.getBedCoordinates()[1:]
         block, room_nr, bed_nr = coordinates
-        self.context.bed_coordinates = '%s, Block %s, Room %s, Bed %s' % (
-            hall_title, block, room_nr, bed_nr)
-        self.flash('Student relocated and new bed booked: %s'
-            % self.context.bed_coordinates)
+        self.context.bed_coordinates = '%s, Block %s, Room %s, Bed %s (%s)' % (
+            hall_title, block, room_nr, bed_nr, new_bed.bed_type)
+        self.flash('Student relocated: %s' % self.context.bed_coordinates)
         self.redirect(self.url(self.context))
         return
 
     def render(self):
-        self.redirect(self.url(self.context, '@@index'))
+        #self.redirect(self.url(self.context, '@@index'))
         return
 
Index: main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/containermanagepage.pt
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/containermanagepage.pt	(revision 7067)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/containermanagepage.pt	(revision 7068)
@@ -10,4 +10,5 @@
     <option value="student_id">with id</option>
     <option value="fullname">with name</option>
+    <option value="current_session">in session</option>
   </select>
 
Index: main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/containerpage.pt
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/containerpage.pt	(revision 7067)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/containerpage.pt	(revision 7068)
@@ -12,4 +12,5 @@
     <option value="reg_number">with registration number</option>
     <option value="matric_number">with matriculation number</option>
+    <option value="current_session">in session</option>
   </select>
 
Index: main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_browser.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_browser.py	(revision 7067)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_browser.py	(revision 7068)
@@ -961,5 +961,5 @@
         self.browser.getLink("Relocate student").click()
         self.assertMatches(
-            "...Bed category hasn't changed...", self.browser.contents)
+            "...Student can't be relocated...", self.browser.contents)
         self.student.sex = u'f'
         self.browser.getLink("Relocate student").click()
@@ -977,15 +977,43 @@
         # Managers can relocate students if the bed's bed_type has changed
         bed1.bed_type = u'regular_female_fr'
-        bed2.bed_type = u'regular_male_reserved'
+        bed2.bed_type = u'regular_male_fr'
         notify(grok.ObjectModifiedEvent(bed1))
         notify(grok.ObjectModifiedEvent(bed2))
         self.browser.getLink("Relocate student").click()
         self.assertMatches(
-            "...Student relocated and new bed booked...", self.browser.contents)
+            "...Student relocated...", self.browser.contents)
         self.assertMatches(
             "... Hall 1, Block A, Room 101, Bed A...", self.browser.contents)
         self.assertMatches(bed1.owner, self.student_id)
         self.assertMatches(bed2.owner, NOT_OCCUPIED)
-        # Managers can delete bed tickets
+        # Managers can't relocate students if bed is reserved
+        self.student.sex = u'm'
+        bed1.bed_type = u'regular_female_reserved'
+        notify(grok.ObjectModifiedEvent(bed1))
+        self.browser.getLink("Relocate student").click()
+        self.assertMatches(
+            "...Students in reserved beds can't be relocated...",
+            self.browser.contents)
+        # Managers can relocate students if booking has been cancelled but
+        # other bed space has been manually allocated after cancellation
+        old_owner = bed1.releaseBed()
+        self.assertMatches(old_owner, self.student_id)
+        bed2.owner = self.student_id
+        self.browser.open(self.acco_student_path + '/2004')
+        self.assertMatches(
+            "...booking cancelled...", self.browser.contents)
+        self.browser.getLink("Relocate student").click()
+        # We didn't informed the catalog therefore the new owner is not found
+        self.assertMatches(
+            "...There is no free bed in your category regular_male_fr...",
+            self.browser.contents)
+        # Now we fire the event properly
+        notify(grok.ObjectModifiedEvent(bed2))
+        self.browser.getLink("Relocate student").click()
+        self.assertMatches(
+            "...Student relocated...", self.browser.contents)
+        self.assertMatches(
+            "... Hall 1, Block A, Room 101, Bed B...", self.browser.contents)
+          # Managers can delete bed tickets
         self.browser.open(self.acco_student_path)
         ctrl = self.browser.getControl(name='val_id')
