Index: main/waeup.kofa/trunk/CHANGES.txt
===================================================================
--- main/waeup.kofa/trunk/CHANGES.txt	(revision 13483)
+++ main/waeup.kofa/trunk/CHANGES.txt	(revision 13484)
@@ -4,4 +4,6 @@
 1.3.4.dev0 (unreleased)
 =======================
+
+* Add bed statistics components.
 
 * Add option which allows students to select a desired hostel before
Index: main/waeup.kofa/trunk/docs/source/userdocs/students/workflow.rst
===================================================================
--- main/waeup.kofa/trunk/docs/source/userdocs/students/workflow.rst	(revision 13483)
+++ main/waeup.kofa/trunk/docs/source/userdocs/students/workflow.rst	(revision 13484)
@@ -6,15 +6,15 @@
 Studying at a higher education institution means following
 orchestrated and repeatable patterns of activities or, in other
-words, following a workflow prescribed by the school regulations.
-This process starts with application for studying a programme
-offered by the school, and may end with de-registration of a
-student. But even after de-registration, former students can be kept
-in the system as alumni so that they can still access their records
-or can apply for official transcripts.
+words, following a process workflow prescribed by the school
+regulations. This process starts with application for studying a
+programme offered by the school, and may end with de-registration of
+a student. But even after de-registration, former students can be
+kept in the system as alumni so that they can still access their
+records or can apply for official transcripts.
 
 Kofa divides these 'repeatable patterns of activities' into two
-different and strictly seperated workflows: an application and a
-student registration workflow. The latter, which presupposes the
-admission of the student, will be described here.
+different and strictly seperated process workflows: an application
+and a student registration workflow. The latter, which presupposes
+the admission of the student, will be described here.
 
 A worflow defines states and transitions between the states. The
Index: main/waeup.kofa/trunk/src/waeup/kofa/hostels/browser.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/hostels/browser.py	(revision 13483)
+++ main/waeup.kofa/trunk/src/waeup/kofa/hostels/browser.py	(revision 13484)
@@ -115,4 +115,13 @@
     text = _('Manage accommodation section')
 
+class HostelsStatisticsActionButton(ManageActionButton):
+    grok.order(2)
+    grok.context(IHostelsContainer)
+    grok.view(HostelsContainerPage)
+    grok.require('waeup.manageHostels')
+    icon = 'actionicon_statistics.png'
+    text = _('Bed statistics')
+    target = 'statistics'
+
 class HostelsContainerManagePage(KofaEditFormPage):
     """The manage page for hostel containers.
@@ -196,4 +205,13 @@
     def render(self):
         return
+
+class HostelsStatisticsPage(KofaDisplayFormPage):
+    """Some statistics about beds in hostels.
+    """
+    grok.context(IHostelsContainer)
+    grok.name('statistics')
+    grok.require('waeup.manageHostels')
+    grok.template('containerstatistics')
+    label = _('Bed Statistics')
 
 class HostelAddFormPage(KofaAddFormPage):
Index: main/waeup.kofa/trunk/src/waeup/kofa/hostels/browser_templates/containerstatistics.pt
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/hostels/browser_templates/containerstatistics.pt	(revision 13484)
+++ main/waeup.kofa/trunk/src/waeup/kofa/hostels/browser_templates/containerstatistics.pt	(revision 13484)
@@ -0,0 +1,20 @@
+<tal:statistics define="stats context/statistics" i18n:domain="waeup.kofa">
+  <table class="table">
+    <thead>
+      <tr>
+        <th i18n:translate="" width="40%">Bed Type</th>
+        <th i18n:translate="">Occupied</th>
+        <th i18n:translate="">Free</th>
+        <th i18n:translate="">Total</th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr tal:repeat="bed_type python:sorted(stats.keys())">
+        <td tal:content="bed_type">TYPE</td>
+        <td style="width: 100px;" tal:content="python: stats[bed_type][0]">OCCUPIED</td>
+        <td style="width: 100px;" tal:content="python: stats[bed_type][1]">FREE</td>
+        <td style="width: 100px;" tal:content="python: stats[bed_type][2]">TOTAL</td>
+      </tr>
+    </tbody>
+  </table>
+</tal:statistics>
Index: main/waeup.kofa/trunk/src/waeup/kofa/hostels/tests.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/hostels/tests.py	(revision 13483)
+++ main/waeup.kofa/trunk/src/waeup/kofa/hostels/tests.py	(revision 13484)
@@ -238,12 +238,14 @@
         stats = utils.getBedStatistics()
         self.assertEqual(stats,
-            {'regular_male_fr': (1, 1),
-             'regular_female_fi': (0, 0),
-             'regular_male_re': (0, 0),
-             'regular_female_fr': (0, 0),
-             'regular_female_all': (0, 0),
-             'regular_female_re': (0, 0),
-             'regular_male_fi': (0, 0),
-             'regular_male_all': (0, 0)}
+            {'regular_male_fr': (0, 1, 1),
+             'regular_female_fi': (0, 0, 0),
+             'regular_male_re': (0, 0, 0),
+             'regular_female_fr': (0, 0, 0),
+             'regular_female_all': (0, 0, 0),
+             'regular_female_re': (0, 0, 0),
+             'regular_female_reserved': (0, 0, 0),
+             'regular_male_reserved': (0, 0, 0),
+             'regular_male_fi': (0, 0, 0),
+             'regular_male_all': (0, 0, 0)}
              )
         self.app[
@@ -253,12 +255,14 @@
         stats = utils.getBedStatistics()
         self.assertEqual(stats,
-            {'regular_male_fr': (0, 1),
-             'regular_female_fi': (0, 0),
-             'regular_male_re': (0, 0),
-             'regular_female_fr': (0, 0),
-             'regular_female_all': (0, 0),
-             'regular_female_re': (0, 0),
-             'regular_male_fi': (0, 0),
-             'regular_male_all': (0, 0)}
+            {'regular_male_fr': (1, 0, 1),
+             'regular_female_fi': (0, 0, 0),
+             'regular_male_re': (0, 0, 0),
+             'regular_female_fr': (0, 0, 0),
+             'regular_female_all': (0, 0, 0),
+             'regular_female_re': (0, 0, 0),
+             'regular_female_reserved': (0, 0, 0),
+             'regular_male_reserved': (0, 0, 0),
+             'regular_male_fi': (0, 0, 0),
+             'regular_male_all': (0, 0, 0)}
              )
 
@@ -478,4 +482,7 @@
         self.assertTrue('2 of 10' in self.browser.contents)
         bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
+        # Managers can open the bed statistics page
+        self.browser.getLink("Bed statistics").click()
+        self.assertTrue('Bed Statistics</h1>' in self.browser.contents)
         # Remove entire hostel.
         self.browser.open(self.manage_container_path)
Index: main/waeup.kofa/trunk/src/waeup/kofa/hostels/utils.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/hostels/utils.py	(revision 13483)
+++ main/waeup.kofa/trunk/src/waeup/kofa/hostels/utils.py	(revision 13484)
@@ -39,14 +39,19 @@
             'regular_female_fi',
             'regular_female_all',
+            'regular_female_reserved',
             'regular_male_fr',
             'regular_male_re',
             'regular_male_fi',
-            'regular_male_all',)
+            'regular_male_all',
+            'regular_male_reserved',)
         for bed_type in bed_types:
-            no = cat.searchResults(
+            free = cat.searchResults(
                 bed_type=(bed_type, bed_type),
                 owner=(NOT_OCCUPIED, NOT_OCCUPIED))
             all = cat.searchResults(
                 bed_type=(bed_type, bed_type))
-            stats[bed_type] = (len(no), len(all))
+            free = len(free)
+            total = len(all)
+            occ = total - free
+            stats[bed_type] = (occ, free, total)
         return stats
