diff --git a/app/controllers/consultation/admin.php b/app/controllers/consultation/admin.php
index 12c77a7edb98d2dbb52d060a3b42479266ff55c7..0ca50b37c0297cfacac59d0f416b362e54a0790e 100644
--- a/app/controllers/consultation/admin.php
+++ b/app/controllers/consultation/admin.php
@@ -140,11 +140,11 @@ class Consultation_AdminController extends ConsultationController
 
             $block = new ConsultationBlock();
             $block->range = $this->range;
-            $this->responsible = $block->responsible_persons;
+            $this->responsible = $block->getPossibleResponsibilites();
         } elseif ($this->range instanceof Institute) {
             $block = new ConsultationBlock();
             $block->range = $this->range;
-            $this->responsible = $block->responsible_persons;
+            $this->responsible = $block->getPossibleResponsibilites();
         }
     }
 
@@ -182,10 +182,20 @@ class Consultation_AdminController extends ConsultationController
                 $block->confirmation_text = trim(Request::get('confirmation-text')) ?: null;
                 $block->note              = Request::get('note');
                 $block->size              = Request::int('size', 1);
-                $block->teacher_id        = Request::option('teacher_id') ?: null;
 
                 $block->createSlots(Request::int('duration'));
                 $stored += $block->store();
+
+                // Store block responsibilites
+                foreach (Request::getArray('responsibilities') as $type => $ids) {
+                    foreach ($ids as $id) {
+                        ConsultationResponsibility::create([
+                            'block_id'   => $block->id,
+                            'range_id'   => $id,
+                            'range_type' => $type,
+                        ]);
+                    }
+                }
             }
         } catch (OverlapException $e) {
             $this->keepRequest();
@@ -211,13 +221,9 @@ class Consultation_AdminController extends ConsultationController
         $this->relocate('consultation/admin');
     }
 
-    public function note_action($block_id, $slot_id = null, $page = 0)
+    public function note_action($block_id, $slot_id, $page = 0)
     {
-        if ($slot_id) {
-            PageLayout::setTitle(_('Anmerkung zu diesem Termin bearbeiten'));
-        } else {
-            PageLayout::setTitle(_('Anmerkung zu diesem Block bearbeiten'));
-        }
+        PageLayout::setTitle(_('Anmerkung zu diesem Termin bearbeiten'));
 
         $this->block   = $this->loadBlock($block_id);
         $this->slot_id = $slot_id;
@@ -228,20 +234,10 @@ class Consultation_AdminController extends ConsultationController
 
             $note = trim(Request::get('note'));
 
-            $changed = false;
-            if ($slot_id) {
-                $slot = $this->block->slots->find($slot_id);
-                $slot->note = $note;
-                $changed = $slot->store();
-            } else {
-                $this->block->note = $note;
-                foreach ($this->block->slots as $slot) {
-                    $slot->note = '';
-                }
-                $changed = $this->block->store();
-            }
-            if ($changed) {
-                PageLayout::postSuccess(_('Der Block wurde bearbeitet'));
+            $slot = $this->block->slots->find($slot_id);
+            $slot->note = $note;
+            if ($slot->store()) {
+                PageLayout::postSuccess(_('Die Anmerkung wurde bearbeitet'));
             }
 
             if ($this->block->is_expired) {
@@ -344,20 +340,60 @@ class Consultation_AdminController extends ConsultationController
         }
     }
 
-    public function edit_room_action($block_id, $page = 0)
+    public function edit_action($block_id, $page = 0)
     {
-        PageLayout::setTitle(_('Ort des Blocks bearbeiten'));
+        PageLayout::setTitle(_('Block bearbeiten'));
 
         $this->block = $this->loadBlock($block_id);
         $this->page  = $page;
+
+        $this->responsible = false;
+        if ($this->block->range instanceof Course || $this->block->range instanceof Institute) {
+            $this->responsible = $this->block->getPossibleResponsibilites();
+        }
     }
 
-    public function store_room_action($block_id, $page = 0)
+    public function store_edited_action($block_id, $page = 0)
     {
         CSRFProtection::verifyUnsafeRequest();
 
         $this->block = $this->loadBlock($block_id);
-        $this->block->room = Request::get('room');
+        $this->block->room = trim(Request::get('room'));
+        $this->block->note = trim(Request::get('note'));
+
+        foreach ($this->block->slots as $slot) {
+            $slot->note = '';
+        }
+
+        // Store block responsibilites
+        $responsibilities = array_merge(
+            ['user' => [], 'statusgroup' => [], 'institute' => []],
+            Request::getArray('responsibilities')
+        );
+        foreach ($responsibilities as $type => $ids) {
+            $of_type = $this->block->responsibilities->filter(function ($responsibility) use ($type) {
+                return $responsibility->range_type === $type;
+            });
+
+            // Delete removed responsibilites
+            $of_type->each(function ($responsibility) use ($ids) {
+                if (!in_array($responsibility->range_id, $ids)) {
+                    $responsibility->delete();
+                }
+            });
+            // Add new responsibilities
+            foreach ($ids as $id) {
+                if (!$of_type->findOneBy('range_id', $id)) {
+                    ConsultationResponsibility::create([
+                        'block_id'   => $this->block->id,
+                        'range_id'   => $id,
+                        'range_type' => $type,
+                    ]);
+                }
+            }
+        }
+
+
         $this->block->store();
 
         PageLayout::postSuccess(_('Der Block wurde gespeichert.'));
@@ -577,7 +613,6 @@ class Consultation_AdminController extends ConsultationController
             function ($slot) use (&$deleted) {
                 $index = $slot->is_expired ? 'expired' : 'current';
 
-                $slot->removeEvent();
                 $deleted[$index] += $slot->delete();
             },
             "JOIN consultation_blocks USING (block_id) WHERE range_id = ? AND range_type = ?",
diff --git a/app/controllers/consultation/consultation_controller.php b/app/controllers/consultation/consultation_controller.php
index c69ab16584b1057389f91cdbeddd72822c6d77b7..eba81ff4967ce57ce8f97dd9857e95c1d77e1ab1 100644
--- a/app/controllers/consultation/consultation_controller.php
+++ b/app/controllers/consultation/consultation_controller.php
@@ -77,6 +77,12 @@ abstract class ConsultationController extends AuthenticatedController
         $this->flash['request'] = Request::getInstance()->getIterator()->getArrayCopy();
     }
 
+    /**
+     * @param $block_id
+     *
+     * @return ConsultationBlock|ConsultationBlock[]
+     * @throws AccessDeniedException
+     */
     protected function loadBlock($block_id)
     {
         if (is_array($block_id)) {
diff --git a/app/views/consultation/admin/block-responsibilities.php b/app/views/consultation/admin/block-responsibilities.php
new file mode 100644
index 0000000000000000000000000000000000000000..ea3531a0295e37d991a97d9e73c3de2af41d6bc9
--- /dev/null
+++ b/app/views/consultation/admin/block-responsibilities.php
@@ -0,0 +1,50 @@
+<?php
+$block = $block ?? false;
+$selected = function ($type, $id) use ($block) {
+    if (!$block ) {
+        return '';
+    }
+    $matched = $block->responsibilities->filter(function ($responsibility) use ($type, $id) {
+        return $responsibility->range_type === $type && $responsibility->range_id === $id;
+    });
+    return count($matched) > 0 ? 'selected' : '';
+}
+?>
+<? if (!empty($responsible['users'])): ?>
+    <label>
+        <?= _('Durchführende Person(en)') ?>
+        <select name="responsibilities[user][]" multiple class="nested-select">
+            <? foreach ($responsible['users'] as $user): ?>
+                <option value="<?= htmlReady($user->id) ?>" <?= $selected('user', $user->id) ?>>
+                    <?= htmlReady($user->getFullName()) ?>
+                </option>
+            <? endforeach; ?>
+        </select>
+    </label>
+<? endif; ?>
+
+<? if (!empty($responsible['groups'])): ?>
+    <label>
+        <?= _('Durchführende Gruppe(n)') ?>
+        <select name="responsibilities[statusgroup][]" multiple class="nested-select">
+            <? foreach ($responsible['groups'] as $group): ?>
+                <option value="<?= htmlReady($group->id) ?>" <?= $selected('statusgroup', $group->id) ?>>
+                    <?= htmlReady($group->getName()) ?>
+                </option>
+            <? endforeach; ?>
+        </select>
+    </label>
+<? endif; ?>
+
+<? if (!empty($responsible['institutes'])): ?>
+    <label>
+        <?= _('Durchführende Einrichtung(en)') ?>
+        <select name="responsibilities[institute][]" multiple class="nested-select">
+            <? foreach ($responsible['institutes'] as $institute): ?>
+                <option value="<?= htmlReady($institute->id) ?>" <?= $selected('institute', $institute->id) ?>>
+                    <?= htmlReady($institute->getFullname()) ?>
+                </option>
+            <? endforeach; ?>
+        </select>
+    </label>
+<? endif; ?>
diff --git a/app/views/consultation/admin/create.php b/app/views/consultation/admin/create.php
index 4630ceeeb5444d01c6e8c85f3bdbb7d8d8792a36..d8727ef2e797379607632c67322f888bf679c2d4 100644
--- a/app/views/consultation/admin/create.php
+++ b/app/views/consultation/admin/create.php
@@ -36,7 +36,7 @@ $intervals = [
 
     <fieldset>
         <legend>
-            <?= _('Neue Terminblöcke anlegen') ?>
+            <?= _('Ort und Zeit') ?>
         </legend>
 
         <label>
@@ -119,19 +119,18 @@ $intervals = [
             <input required type="text" name="size" id="size"
                    min="1" max="50" value="<?= Request::int('size', 1) ?>">
         </label>
+    </fieldset>
 
-    <? if ($responsible): ?>
-        <label>
-            <?= _('Durchführende Person') ?>
-            <select name="teacher_id">
-                <option value=""></option>
-            <? foreach ($responsible as $user): ?>
-                <option value="<?= htmlReady($user->id) ?>">
-                    <?= htmlReady($user->getFullName()) ?>
-                </option>
-            <? endforeach; ?>
-            </select>
-    <? endif; ?>
+<? if ($responsible): ?>
+    <fieldset>
+        <legend><?= _('Durchführende Person(en), Gruppe(n) oder Einrichtung(en)') ?></legend>
+
+        <?= $this->render_partial('consultation/admin/block-responsibilities.php', compact('responsible')) ?>
+    </fieldset>
+<? endif; ?>
+
+    <fieldset>
+        <legend><?= _('Weitere Einstellungen') ?></legend>
 
         <label>
             <?= _('Information zu den Terminen in diesem Block') ?>
diff --git a/app/views/consultation/admin/edit.php b/app/views/consultation/admin/edit.php
new file mode 100644
index 0000000000000000000000000000000000000000..6f1911a1e1a6be7be137d61e5a6fdb404e800423
--- /dev/null
+++ b/app/views/consultation/admin/edit.php
@@ -0,0 +1,34 @@
+<form action="<?= $controller->store_edited($block, $page) ?>" method="post" class="default">
+    <?= CSRFProtection::tokenTag() ?>
+
+    <?= MessageBox::info(
+        _('Das Ändern der Informationen wird auch alle Termine dieses Blocks ändern.')
+    )->hideClose() ?>
+
+    <fieldset>
+        <legend><?= _('Terminblock bearbeiten') ?></legend>
+
+        <label>
+            <span class="required"><?= _('Ort') ?></span>
+            <input required type="text" name="room" placeholder="<?= _('Ort') ?>"
+                   value="<?= htmlReady($block->room) ?>">
+        </label>
+
+        <label>
+            <?=_('Information zu den Terminen in diesem Block') ?> (<?= _('Öffentlich einsehbar') ?>)
+            <textarea name="note"><?= htmlReady($block->note ) ?></textarea>
+        </label>
+
+    <? if ($responsible): ?>
+        <?= $this->render_partial('consultation/admin/block-responsibilities.php', compact('responsible', 'block')) ?>
+    <? endif; ?>
+    </fieldset>
+
+    <footer data-dialog-button>
+        <?= Studip\Button::createAccept(_('Speichern')) ?>
+        <?= Studip\LinkButton::createCancel(
+            _('Abbrechen'),
+            $controller->indexURL($page)
+        ) ?>
+    </footer>
+</form>
diff --git a/app/views/consultation/admin/edit_room.php b/app/views/consultation/admin/edit_room.php
index 6c5243621c7a847a9eaee1d6089cdb5818e359fa..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/app/views/consultation/admin/edit_room.php
+++ b/app/views/consultation/admin/edit_room.php
@@ -1,21 +0,0 @@
-<form action="<?= $controller->store_room($block, $page) ?>" method="post" class="default">
-    <?= CSRFProtection::tokenTag() ?>
-
-    <fieldset>
-        <legend><?= _('Ort des Terminblocks bearbeiten') ?></legend>
-
-        <label>
-            <span class="required"><?= _('Ort') ?></span>
-            <input required type="text" name="room" placeholder="<?= _('Ort') ?>"
-                   value="<?= htmlReady($block->room) ?>">
-        </label>
-    </fieldset>
-
-    <footer data-dialog-button>
-        <?= Studip\Button::createAccept(_('Speichern')) ?>
-        <?= Studip\LinkButton::createCancel(
-            _('Abbrechen'),
-            $controller->indexURL($page)
-        ) ?>
-    </footer>
-</form>
diff --git a/app/views/consultation/admin/index.php b/app/views/consultation/admin/index.php
index 5d0a7dac0d14da6a9e830bd8ed2785df4fd8843f..6ee75508c5e6920d00b274342961e4727def9052 100644
--- a/app/views/consultation/admin/index.php
+++ b/app/views/consultation/admin/index.php
@@ -45,13 +45,8 @@
             </th>
             <th class="actions">
                 <?= ActionMenu::get()->addLink(
-                    $controller->edit_roomURL($block['block'], $page),
-                    _('Raum bearbeiten'),
-                    Icon::create('edit'),
-                    ['data-dialog' => 'size=auto']
-                )->addLink(
-                    $controller->noteURL($block['block'], 0, $page),
-                    _('Information bearbeiten'),
+                    $controller->editURL($block['block'], 0, $page),
+                    _('Bearbeiten'),
                     Icon::create('edit'),
                     ['data-dialog' => 'size=auto']
                 )->addLink(
diff --git a/app/views/consultation/block-description.php b/app/views/consultation/block-description.php
index df3d0bd5c77d6d0fa8b5f756a8a0ad9080a58ffb..4d037ff5c4fa862226d3156670eadc3e7518479a 100644
--- a/app/views/consultation/block-description.php
+++ b/app/views/consultation/block-description.php
@@ -6,13 +6,6 @@
     date('H:i', $block->end)
 ) ?>
 
-<? if ($block->teacher): ?>
-/
-<a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $block->teacher->username]) ?>">
-    <?= htmlReady($block->teacher->getFullName()) ?>
-</a>
-<? endif; ?>
-
 (<?= formatLinks($block->room) ?>)
 
 <? if ($block->show_participants): ?>
@@ -20,6 +13,19 @@
     <?= tooltipIcon(_('Die Namen der buchenden Person sind sichtbar')) ?>
 <? endif; ?>
 
+<? if (count($block->responsibilities) > 0): ?>
+<br>
+<ul class="narrow list-csv">
+<? foreach ($block->responsibilities as $responsibility): ?>
+    <li>
+        <a href="<?= URLHelper::getLink($responsibility->getURL(), [], true) ?>">
+            <?= htmlReady($responsibility->getName()) ?>
+        </a>
+    </li>
+<? endforeach; ?>
+</ul>
+<? endif; ?>
+
 <? if ($block->note): ?>
 <br>
 <small>
diff --git a/db/migrations/1.269_fix_missing_consultation_events.php b/db/migrations/1.269_fix_missing_consultation_events.php
index 1432458abf10aabb11cd97f0693f6579be48b90a..a0548e0dd1aa3a6a41476c1e3d4692b34b948ca4 100644
--- a/db/migrations/1.269_fix_missing_consultation_events.php
+++ b/db/migrations/1.269_fix_missing_consultation_events.php
@@ -26,7 +26,7 @@ class FixMissingConsultationEvents extends Migration
                 // has code changes for Stud.IP 5.0 this will fail but we can neglect
                 // that since the event is already updated.
                 try {
-                    $slot->updateEvent();
+                    $slot->updateEvents();
                 } catch (Exception $e) {
                 }
             },
@@ -41,10 +41,11 @@ class LegacyConsultationSlot extends ConsultationSlot
      * Updates the teacher event that belongs to the slot. This will either be
      * set to be unoccupied, occupied by only one user or by a group of user.
      */
-    public function updateEvent()
+    public function updateEvents()
     {
         if (count($this->bookings) === 0 && !$this->block->calendar_events) {
-            return $this->removeEvent();
+            $this->events->delete();
+            return;
         }
 
         $teacher = User::find($this->block->teacher_id);
diff --git a/db/migrations/5.1.7_consultation_multiple_responsible_ranges.php b/db/migrations/5.1.7_consultation_multiple_responsible_ranges.php
new file mode 100644
index 0000000000000000000000000000000000000000..1daf474eb7d0165445a57e66dafd93e80073fc83
--- /dev/null
+++ b/db/migrations/5.1.7_consultation_multiple_responsible_ranges.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * @see https://gitlab.studip.de/studip/studip/-/issues/132
+ */
+final class ConsultationMultipleResponsibleRanges extends Migration
+{
+    public function description()
+    {
+        return 'Adjust database to allow multiple responsible ranges for consultations';
+    }
+
+    protected function up()
+    {
+        $query = "CREATE TABLE IF NOT EXISTS `consultation_responsibilities` (
+                    `block_id` INT(11) UNSIGNED NOT NULL,
+                    `range_id` CHAR(32) CHARSET latin1 COLLATE latin1_bin NOT NULL,
+                    `range_type` ENUM('user', 'institute', 'statusgroup') CHARSET latin1 COLLATE latin1_bin NOT NULL,
+                    `mkdate` INT(11) UNSIGNED NOT NULL,
+                    PRIMARY KEY (`block_id`, `range_id`, `range_type`)
+                  )";
+        DBManager::get()->exec($query);
+
+        $query = "CREATE TABLE IF NOT EXISTS `consultation_events` (
+                    `slot_id` INT(11) UNSIGNED NOT NULL,
+                    `user_id` CHAR(32) CHARSET latin1 COLLATE latin1_bin NOT NULL,
+                    `mkdate` INT(11) UNSIGNED NOT NULL,
+                    PRIMARY KEY (`slot_id`, `user_id`)
+                  )";
+        DBManager::get()->exec($query);
+
+        $query = "INSERT IGNORE INTO `consultation_responsibilities` (
+                     `block_id`, `range_id`, `range_type`, `mkdate`
+                  )
+                  SELECT `block_id`, `teacher_id`, 'user', UNIX_TIMESTAMP()
+                  FROM `consultation_blocks`
+                  WHERE `teacher_id` IS NOT NULL";
+        DBManager::get()->exec($query);
+
+        $query = "INSERT IGNORE INTO `consultation_events` (
+                     `slot_id`, `user_id`, `event_id`, `mkdate`
+                  )
+                  SELECT `slot_id`, `teacher_id`, `teacher_event_id`, UNIX_TIMESTAMP()
+                  FROM `consultation_blocks`
+                  JOIN `consultation_slots` USING (`block_id`)
+                  WHERE `teacher_event_id` IS NOT NULL";
+        DBManager::get()->exec($query);
+
+        $query = "ALTER TABLE `consultation_blocks`
+                  DROP COLUMN `teacher_id`";
+        DBManager::get()->exec($query);
+
+        $query = "ALTER TABLE `consultation_slots`
+                  DROP COLUMN `teacher_event_id`";
+        DBManager::get()->exec($query);
+    }
+
+    protected function down()
+    {
+        $query = "ALTER TABLE `consultation_slots`
+                  ADD COLUMN `teacher_event_id` CHAR(32) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL AFTER `note`";
+        DBManager::get()->exec($query);
+
+        $query = "ALTER TABLE `consultation_blocks`
+                  ADD COLUMN `teacher_id` CHAR(32) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL";
+        DBManager::get()->exec($query);
+
+        $query = "UPDATE `consultation_slots` AS cs
+                  JOIN `consultation_events` AS ce USING (`slot_id`)
+                  JOIN `consultation_blocks` AS cb USING (`block_id`)
+                  SET cs.`teacher_event_id` = ce.`event_id`
+                  WHERE cb.`range_type` = 'user'
+                    AND cs.`slot_id` IN (
+                        SELECT `slot_id`
+                        FROM `consultation_events`
+                        GROUP BY `slot_id`
+                        HAVING COUNT(*) = 1
+                    )";
+        DBManager::get()->exec($query);
+
+        $query = "UPDATE `consultation_blocks` AS cb
+                  JOIN `consultation_responsibilities` AS cr USING (`block_id`)
+                  SET cb.`teacher_id` = cr.`range_id`
+                  WHERE cb.`block_id` IN (
+                        SELECT `block_id`
+                        FROM `consultation_responsibilities` AS cr2
+                        JOIN `consultation_blocks` AS cb USING (`block_id`)
+                        WHERE cr2.`range_type` = 'user'
+                        GROUP BY `block_id`
+                        HAVING COUNT(DISTINCT cr.`range_id`) = 1
+                    )";
+        DBManager::get()->exec($query);
+
+        $query = "DROP TABLE IF EXISTS `consultation_events`";
+        DBManager::get()->exec($query);
+
+        $query = "DROP TABLE IF EXISTS `consultation_responsibilities`";
+        DBManager::get()->exec($query);
+    }
+}
diff --git a/lib/classes/ConsultationMailer.php b/lib/classes/ConsultationMailer.php
index 007bb472d109f27f5f2d58fc8ed85f221a35423c..b9713dc55f9fe8a15da3ed7da805bf5aa23eed8b 100644
--- a/lib/classes/ConsultationMailer.php
+++ b/lib/classes/ConsultationMailer.php
@@ -54,9 +54,13 @@ class ConsultationMailer
      *
      * @param  ConsultationBooking $booking The booking
      */
-    public static function sendBookingMessageToTeacher(ConsultationBooking $booking)
+    public static function sendBookingMessageToResponsibilities(ConsultationBooking $booking)
     {
         foreach ($booking->slot->block->responsible_persons as $user) {
+            if ($user->id === $GLOBALS['user']->id) {
+                continue;
+            }
+
             self::sendMessage(
                 $user,
                 $booking,
@@ -94,7 +98,7 @@ class ConsultationMailer
         self::sendMessage(
             $receiver,
             $booking->slot,
-            sprintf(_('Grund des Termins bei bearbeitet'), $booking->slot->block->range_display),
+            sprintf(_('Grund des Termins bei %s bearbeitet'), $booking->slot->block->range_display),
             $booking->reason
         );
     }
@@ -105,9 +109,13 @@ class ConsultationMailer
      * @param  ConsultationBooking $booking The booking
      * @param  String              $reason  Reason of the cancelation
      */
-    public static function sendCancelMessageToTeacher(ConsultationBooking $booking, $reason = '')
+    public static function sendCancelMessageToResponsibilities(ConsultationBooking $booking, $reason = '')
     {
         foreach ($booking->slot->block->responsible_persons as $user) {
+            if ($user->id === $GLOBALS['user']->id) {
+                continue;
+            }
+
             self::sendMessage(
                 $user,
                 $booking,
diff --git a/lib/models/CalendarEvent.class.php b/lib/models/CalendarEvent.class.php
index f0a4a8711a654efa5b868191abd1fca5ea3b5c9a..a61922c2c7db82b753686df9e58d44a922de82c1 100644
--- a/lib/models/CalendarEvent.class.php
+++ b/lib/models/CalendarEvent.class.php
@@ -69,10 +69,10 @@ class CalendarEvent extends SimpleORMap implements Event, PrivacyObject
             'foreign_key'       => 'event_id',
             'assoc_foreign_key' => 'student_event_id',
         ];
-        $config['belongs_to']['consultation_slot'] = [
-            'class_name'        => ConsultationSlot::class,
+        $config['has_many']['consultation_events'] = [
+            'class_name'        => ConsultationEvent::class,
             'foreign_key'       => 'event_id',
-            'assoc_foreign_key' => 'teacher_event_id',
+            'assoc_foreign_key' => 'event_id',
         ];
         $config['additional_fields']['type'] = true;
         $config['additional_fields']['name'] = true;
@@ -88,10 +88,7 @@ class CalendarEvent extends SimpleORMap implements Event, PrivacyObject
                 $event->consultation_booking->student_event_id = null;
                 $event->consultation_booking->store();
             }
-            if ($event->consultation_slot) {
-                $event->consultation_slot->teacher_event_id = null;
-                $event->consultation_slot->store();
-            }
+            $event->consultation_events->delete();
         };
 
         parent::configure($config);
@@ -1018,21 +1015,18 @@ class CalendarEvent extends SimpleORMap implements Event, PrivacyObject
     }
 
     /**
-     *
-     * TODO remove! not used?
-     *
-     * @return type
+     * @return string
      */
     public function getName()
     {
         switch ($this->type) {
             case 'user':
-                return $this->user->getFullname();
+                return (string) $this->user->getFullname();
             case 'sem':
-                return $this->course->name;
+                return (string) $this->course->name;
             case 'inst':
             case 'fak':
-                return $this->institute->name;
+                return (string) $this->institute->name;
             }
     }
 
diff --git a/lib/models/ConsultationBlock.php b/lib/models/ConsultationBlock.php
index bb83515165723e53d5188af6fabf6c46a6e4cb26..d64462988e1b4b91f97252cf3b8d3da76664d364 100644
--- a/lib/models/ConsultationBlock.php
+++ b/lib/models/ConsultationBlock.php
@@ -24,7 +24,8 @@
  * @property bool has_bookings computed column
  * @property Range range computed column
  * @property SimpleORMapCollection slots has_many ConsultationSlot
- * @property User teacher belongs_to User
+ * @property ConsultationResponsibility[] responsibilities has_many ConsultationResponsibility
+ * @property User[] responsible_persons
  */
 class ConsultationBlock extends SimpleORMap implements PrivacyObject
 {
@@ -36,16 +37,18 @@ class ConsultationBlock extends SimpleORMap implements PrivacyObject
     {
         $config['db_table'] = 'consultation_blocks';
 
-        $config['belongs_to']['teacher'] = [
-            'class_name'  => User::class,
-            'foreign_key' => 'teacher_id',
-        ];
         $config['has_many']['slots'] = [
             'class_name'        => ConsultationSlot::class,
             'assoc_foreign_key' => 'block_id',
             'on_store'          => 'store',
             'on_delete'         => 'delete',
         ];
+        $config['has_many']['responsibilities'] = [
+            'class_name'        => ConsultationResponsibility::class,
+            'assoc_foreign_key' => 'block_id',
+            'on_delete'         => 'delete',
+            'order_by'          => "ORDER BY range_type = 'user' DESC, range_type = 'statusgroup' DESC",
+        ];
 
         $config['additional_fields']['range'] = [
             'set' => function ($block, $field, Range $range) {
@@ -61,31 +64,11 @@ class ConsultationBlock extends SimpleORMap implements PrivacyObject
                 return $block->range->getFullName() . ' <' . $block->range->email . '>';
             }
             if ($block->range instanceof Course || $block->range instanceof Institute) {
-                $display = $block->range->getFullName();
-                if ($block->teacher) {
-                    $display .= ' (' . $block->teacher->getFullName() . ')';
-                }
-                return $display;
-            }
-
-            throw new Exception('Not implemented yet');
-        };
-        $config['additional_fields']['responsible_persons']['get'] = function ($block) {
-            if ($block->range instanceof User) {
-                return [$block->range];
-            }
-            if ($block->range instanceof Course && $block->teacher) {
-                return [$block->teacher];
-            }
-
-            if ($block->range instanceof Course) {
-                return $block->range->getMembersWithStatus('tutor dozent', true)->pluck('user');
+                return sprintf(_('Veranstaltung: %s'), $block->range->getFullName());
             }
 
             if ($block->range instanceof Institute) {
-                return $block->range->members->filter(function ($member) {
-                    return in_array($member->inst_perms, ['tutor', 'dozent']);
-                })->pluck('user');
+                return sprintf(_('Einrichtung: %s'), $block->range->getFullname());
             }
 
             throw new Exception('Not implemented yet');
@@ -103,6 +86,32 @@ class ConsultationBlock extends SimpleORMap implements PrivacyObject
             });
         };
 
+        $config['additional_fields']['responsible_persons']['get'] = function (ConsultationBlock $block) {
+            if (count($block->responsibilities) !== 0) {
+                $result = [];
+                foreach (array_merge(...$block->responsibilities->getUsers()) as $user) {
+                    $result[$user->id] = $user;
+                }
+                return array_values($result);
+            }
+
+            if ($block->range instanceof User) {
+                return [$block->range];
+            }
+            if ($block->range instanceof Course) {
+                return ConsultationResponsibility::getCourseResponsibilities($block->range);
+            }
+            if ($block->range instanceof Institute) {
+                return ConsultationResponsibility::getInstituteResponsibilites($block->range);
+            }
+
+            throw new Exception('Unknown range type');
+        };
+
+        $config['registered_callbacks']['after_store'][] = function (ConsultationBlock $block) {
+            $block->slots->updateEvents();
+        };
+
         parent::configure($config);
     }
 
@@ -273,6 +282,37 @@ class ConsultationBlock extends SimpleORMap implements PrivacyObject
         return $this->range->isAccessibleToUser();
     }
 
+    /**
+     *
+     */
+    public function getPossibleResponsibilites()
+    {
+        if ($this->range instanceof User) {
+            return [
+                'users' => [$this->range]
+            ];
+        }
+
+        if ($this->range instanceof Course) {
+            return [
+                'users' => $this->range->getMembersWithStatus('tutor dozent', true)->pluck('user'),
+            ];
+        }
+
+        if ($this->range instanceof Institute) {
+            $users = $this->range->members->filter(function ($member) {
+                return in_array($member->inst_perms, ['tutor', 'dozent']);
+            })->pluck('user');
+
+            $groups     = $this->range->status_groups;
+            $institutes = $this->range->sub_institutes;
+
+            return compact('users', 'groups', 'institutes');
+        }
+
+        throw new Exception('Not implemented yet');
+    }
+
     /**
      * Export available data of a given user into a storage object
      * (an instance of the StoredUserData class) for that user.
diff --git a/lib/models/ConsultationBooking.php b/lib/models/ConsultationBooking.php
index 37756e1282fc81e6f608e270427321aa76883ee4..1f269c43765df19becc7129912db796f2e30c739 100644
--- a/lib/models/ConsultationBooking.php
+++ b/lib/models/ConsultationBooking.php
@@ -40,7 +40,8 @@ class ConsultationBooking extends SimpleORMap implements PrivacyObject
             'on_delete'         => 'delete',
         ];
 
-        $config['registered_callbacks']['before_create'][] = function ($booking) {
+        // Create student event
+        $config['registered_callbacks']['before_create'][] = function (ConsultationBooking $booking) {
             setTempLanguage($booking->user_id);
 
             $event = $booking->slot->createEvent($booking->user);
@@ -57,41 +58,37 @@ class ConsultationBooking extends SimpleORMap implements PrivacyObject
             $booking->student_event_id = $event->id;
         };
 
-        $config['registered_callbacks']['after_create'][] = function ($booking) {
+        $config['registered_callbacks']['after_create'][] = function (ConsultationBooking $booking) {
             ConsultationMailer::sendBookingMessageToUser($booking);
-
-            $responsible_persons = $booking->slot->block->responsible_persons;
-            if (!in_array($GLOBALS['user']->id, $responsible_persons)) {
-                ConsultationMailer::sendBookingMessageToTeacher($booking);
-            }
+            ConsultationMailer::sendBookingMessageToResponsibilities($booking);
         };
 
-        $config['registered_callbacks']['before_store'][] = function ($booking) {
+        $config['registered_callbacks']['before_store'][] = function (ConsultationBooking $booking) {
             if (!$booking->isNew() && $booking->isFieldDirty('reason')) {
                 if ($GLOBALS['user']->id !== $booking->user_id) {
                     ConsultationMailer::sendReasonMessage($booking,$booking->user);
                 }
 
                 $responsible_persons = $booking->slot->block->responsible_persons;
-                if (!in_array($GLOBALS['user']->id, $responsible_persons)) {
-                    foreach ($responsible_persons as $user) {
+                foreach ($responsible_persons as $user) {
+                    if ($GLOBALS['user']->id !== $user->id) {
                         ConsultationMailer::sendReasonMessage($booking, $user);
                     }
                 }
             }
         };
 
-        $config['registered_callbacks']['after_store'][] = function ($booking) {
+        $config['registered_callbacks']['after_store'][] = function (ConsultationBooking $booking) {
             if ($booking->event) {
                 $booking->event->description = $booking->reason;
                 $booking->event->store();
             }
 
-            $booking->slot->updateEvent();
+            $booking->slot->updateEvents();
         };
 
-        $config['registered_callbacks']['after_delete'][] = function ($booking) {
-            $booking->slot->updateEvent();
+        $config['registered_callbacks']['after_delete'][] = function (ConsultationBooking $booking) {
+            $booking->slot->updateEvents();
         };
 
         parent::configure($config);
@@ -103,9 +100,7 @@ class ConsultationBooking extends SimpleORMap implements PrivacyObject
             ConsultationMailer::sendCancelMessageToUser($this, $reason);
         }
 
-        if (!in_array($GLOBALS['user']->id, $this->slot->block->responsible_persons)) {
-            ConsultationMailer::sendCancelMessageToTeacher($this, $reason);
-        }
+        ConsultationMailer::sendCancelMessageToResponsibilities($this, $reason);
 
         return $this->delete() ? 1 : 0;
     }
diff --git a/lib/models/ConsultationEvent.php b/lib/models/ConsultationEvent.php
new file mode 100644
index 0000000000000000000000000000000000000000..d02e2d8a0b041219c25eab8fb7a224b5f90bfce7
--- /dev/null
+++ b/lib/models/ConsultationEvent.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * @author  Jan-Hendrik Willms <tleilax+studip@gmail.com>
+ * @license GPL2 or any later version
+ * @since   Stud.IP 5.1
+ *
+ * @property int slot_id database column
+ * @property int id alias column for slot_id
+ * @property string user_id database column
+ * @property string event_id database column
+ * @property int mkdate database column
+ * @property ConsultationSlot slot belongs_to ConsultationSlot
+ * @property EventData event belongs_to Event
+ */
+class ConsultationEvent extends SimpleORMap
+{
+    protected static function configure($config = [])
+    {
+        $config['db_table'] = 'consultation_events';
+
+        $config['belongs_to']['slot'] = [
+            'class_name'  => ConsultationSlot::class,
+            'foreign_key' => 'slot_id',
+        ];
+        $config['belongs_to']['event'] = [
+            'class_name'        => EventData::class,
+            'foreign_key'       => 'event_id',
+            'assoc_foreign_key' => 'event_id',
+            'on_delete'         => 'delete',
+        ];
+
+        parent::configure($config);
+    }
+}
diff --git a/lib/models/ConsultationResponsibility.php b/lib/models/ConsultationResponsibility.php
new file mode 100644
index 0000000000000000000000000000000000000000..9634d415394c8d0ec0e7c59ce35a00164a1fcf94
--- /dev/null
+++ b/lib/models/ConsultationResponsibility.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * @author  Jan-Hendrik Willms <tleilax+studip@gmail.com>
+ * @license GPL2 or any later version
+ * @since   Stud.IP 5.1
+ *
+ * @property int block_id database column
+ * @property int id alias column for block_id
+ * @property string range_id database column
+ * @property string range_type database column
+ * @property int mkdate database column
+ */
+class ConsultationResponsibility extends SimpleORMap
+{
+    protected static function configure($config = [])
+    {
+        $config['db_table'] = 'consultation_responsibilities';
+
+        $config['belongs_to']['block'] = [
+            'class_name'  => ConsultationBlock::class,
+            'foreign_key' => 'block_id',
+        ];
+
+        parent::configure($config);
+    }
+
+    /**
+     * Returns the name of the associated responsibility.
+     *
+     * @return string
+     * @throws Exception
+     */
+    public function getName()
+    {
+        if ($this->range_type === 'user') {
+            return User::find($this->range_id)->getFullName();
+        }
+        if ($this->range_type === 'statusgroup') {
+            return Statusgruppen::find($this->range_id)->getName();
+        }
+        if ($this->range_type === 'institute') {
+            return Institute::find($this->range_id)->getFullName();
+        }
+        throw new Exception('Unknown range type');
+    }
+
+    /**
+     * Returns an url to the associated responsibility.
+     *
+     * @return string
+     * @throws Exception
+     */
+    public function getURL()
+    {
+        if ($this->range_type === 'user') {
+            $user = User::find($this->range_id);
+            return URLHelper::getURL('dispatch.php/profile', ['username' => $user->username], true);
+        }
+        // TODO: Check if staff tab is activated and link to that
+        if ($this->range_type === 'statusgroup') {
+            $institute = Statusgruppen::find($this->range_id)->institute;
+            return URLHelper::getURL('dispatch.php/institute/overview', ['auswahl' => $institute->id], true);
+        }
+        if ($this->range_type === 'institute') {
+            return URLHelper::getURL('dispatch.php/institute/overview', ['auswahl' => $this->range_id], true);
+        }
+        throw new Exception('Unknown range type');
+    }
+
+    /**
+     * Returns all users belonging to the associated responsibility.
+     *
+     * @return array
+     * @throws Exception
+     */
+    public function getUsers()
+    {
+        if ($this->range_type === 'user') {
+            return [User::find($this->range_id)];
+        }
+        if ($this->range_type === 'statusgroup') {
+            $group = Statusgruppen::find($this->range_id);
+            return self::getStatusgroupResponsibilities($group);
+        }
+        if ($this->range_type === 'institute') {
+            $institute = Institute::find($this->range_id);
+            return self::getInstituteResponsibilites($institute);
+        }
+        throw new Exception('Unknown range type');
+    }
+
+    /**
+     * Returns all responsible users for a course.
+     *
+     * @param Course $course
+     * @return array
+     */
+    public static function getCourseResponsibilities(Course $course)
+    {
+        return $course->getMembersWithStatus('tutor dozent', true)->pluck('user');
+    }
+
+    /**
+     * Returns all responsible users for a status group.
+     *
+     * @param Statusgruppen $group
+     * @return array
+     */
+    public static function getStatusgroupResponsibilities(Statusgruppen $group)
+    {
+        return $group->members->pluck('user');
+    }
+
+    /**
+     * Returns all responsible users for an institute.
+     *
+     * @param Institute $institute
+     * @return array
+     */
+    public static function getInstituteResponsibilites(Institute $institute)
+    {
+        return $institute->members->filter(function (InstituteMember $member) {
+            return in_array($member->inst_perms, ['tutor', 'dozent']);
+        })->pluck('user');
+    }
+}
diff --git a/lib/models/ConsultationSlot.php b/lib/models/ConsultationSlot.php
index fd3b05a72940f77a51a4f4f3bf760ebe0ac2c5e3..1177fcec98f986028dfaae5dac96614eb713d448 100644
--- a/lib/models/ConsultationSlot.php
+++ b/lib/models/ConsultationSlot.php
@@ -11,10 +11,9 @@
  * @property string start_time database column
  * @property string end_time database column
  * @property string note database column
- * @property string teacher_event_id database column
  * @property SimpleORMapCollection bookings has_many ConsultationBooking
  * @property ConsultationBlock block belongs_to ConsultationBlock
- * @property EventData event has_one EventData
+ * @property SimpleORMapCollection events has_many EventData
  */
 class ConsultationSlot extends SimpleORMap
 {
@@ -30,24 +29,20 @@ class ConsultationSlot extends SimpleORMap
             'class_name'  => ConsultationBlock::class,
             'foreign_key' => 'block_id',
         ];
-        $config['has_one']['event'] = [
-            'class_name'        => EventData::class,
-            'foreign_key'       => 'teacher_event_id',
-            'assoc_foreign_key' => 'event_id',
-            'on_delete'         => 'delete',
-        ];
         $config['has_many']['bookings'] = [
             'class_name'        => ConsultationBooking::class,
             'assoc_foreign_key' => 'slot_id',
             'on_store'          => 'store',
             'on_delete'         => 'delete',
         ];
+        $config['has_many']['events'] = [
+            'class_name'        => ConsultationEvent::class,
+            'assoc_foreign_key' => 'slot_id',
+            'on_delete'         => 'delete',
+        ];
 
-        $config['registered_callbacks']['before_create'][] = function ($slot) {
-            if ($slot->block->calendar_events && $slot->block->range_type === 'user') {
-                $slot->teacher_event_id = $slot->createEvent($slot->block->range)->id;
-                $slot->updateEvent();
-            }
+        $config['registered_callbacks']['before_create'][] = function (ConsultationSlot $slot) {
+            $slot->updateEvents();
         };
         $config['registered_callbacks']['after_delete'][] = function ($slot) {
             $block = $slot->block;
@@ -196,69 +191,81 @@ class ConsultationSlot extends SimpleORMap
      * Updates the teacher event that belongs to the slot. This will either be
      * set to be unoccupied, occupied by only one user or by a group of user.
      */
-    public function updateEvent()
+    public function updateEvents()
     {
-        if ($this->block->range_type !== 'user') {
-            return;
-        }
-
         // If no range is associated, remove the event
         if (!$this->block->range) {
-            return $this->removeEvent();
+            $this->events->delete();
+            return;
         }
 
         if (count($this->bookings) === 0 && !$this->block->calendar_events) {
-            return $this->removeEvent();
+            $this->events->delete();
+            return;
         }
 
-        $event = $this->event;
-        if (!$event) {
-            $event = $this->createEvent($this->block->range);
+        // Get responsible user ids
+        $responsible_ids = array_map(
+            function (User $user) {
+                return $user->id;
+            },
+            $this->block->responsible_persons
+        );
 
-            $this->teacher_event_id = $event->id;
-            $this->store();
+        // Remove events for no longer responsible users
+        foreach ($this->events as $event) {
+            if (!in_array($event->user_id, $responsible_ids)) {
+                $event->delete();
+            }
         }
 
-        setTempLanguage($this->block->range_id);
+        // Add events for missing responsible users
+        $missing = array_diff($responsible_ids, $this->events->pluck('user_id'));
+        foreach ($missing as $user_id) {
+            $event = $this->createEvent(User::find($user_id));
+            ConsultationEvent::create([
+                'slot_id'  => $this->id,
+                'user_id'  => $user_id,
+                'event_id' => $event->id,
+            ]);
+        }
+
+        // Reset relation in order to account to the above changes
+        $this->resetRelation('events');
+
+        foreach ($this->events as $event) {
+            setTempLanguage($event->user_id);
 
-        if (count($this->bookings) > 0) {
-            $event->category_intern = 1;
+            if (count($this->bookings) > 0) {
+                $event->event->category_intern = 1;
 
-            if (count($this->bookings) === 1) {
-                $booking = $this->bookings->first();
+                if (count($this->bookings) === 1) {
+                    $booking = $this->bookings->first();
 
-                $event->summary = sprintf(
-                    _('Termin mit %s'),
-                    $booking->user->getFullName()
-                );
-                $event->description = $booking->reason;
+                    $event->event->summary = sprintf(
+                        _('Termin mit %s'),
+                        $booking->user->getFullName()
+                    );
+                    $event->event->description = $booking->reason;
+                } else {
+                    $event->event->summary = sprintf(
+                        _('Termin mit %u Personen'),
+                        count($this->bookings)
+                    );
+                    $event->event->description = implode("\n\n----\n\n", $this->bookings->map(function ($booking) {
+                        return "- {$booking->user->getFullName()}:\n{$booking->reason}";
+                    }));
+                }
             } else {
-                $event->summary = sprintf(
-                    _('Termin mit %u Personen'),
-                    count($this->bookings)
-                );
-                $event->description = implode("\n\n----\n\n", $this->bookings->map(function ($booking) {
-                    return "- {$booking->user->getFullName()}:\n{$booking->reason}";
-                }));
+                $event->event->category_intern = 9;
+                $event->event->summary         = _('Freier Termin');
+                $event->event->description     = _('Dieser Termin ist noch nicht belegt.');
             }
-        } else {
-            $event->category_intern = 9;
-            $event->summary         = _('Freier Termin');
-            $event->description     = _('Dieser Termin ist noch nicht belegt.');
-        }
 
-        restoreLanguage();
+            $event->event->store();
 
-        $event->store();
-    }
-
-    public function removeEvent()
-    {
-        if ($this->event) {
-            $this->event->delete();
+            restoreLanguage();
 
-            $this->teacher_event_id = null;
-            $this->store();
         }
     }
 }
diff --git a/lib/models/Course.class.php b/lib/models/Course.class.php
index b958a4b1ab3d531477335dc0c7f4f7dbdeecddb5..f543c88ba9112f40da48c824d1ae3b2a86018f8b 100644
--- a/lib/models/Course.class.php
+++ b/lib/models/Course.class.php
@@ -449,7 +449,7 @@ class Course extends SimpleORMap implements Range, PrivacyObject, StudipItem, Fe
      *
      * @param String|Array $status        the status to filter with
      * @param bool         $as_collection return collection instead of array?
-     * @return Array an array of all those members.
+     * @return Array|SimpleCollection an array of all those members.
      */
     public function getMembersWithStatus($status, $as_collection = false)
     {
diff --git a/lib/models/Institute.class.php b/lib/models/Institute.class.php
index 86120c1e3fac6d5d25c54d09e2223e965e572f7b..743931c8a14dca613403074fc92c5fc68af6460d 100644
--- a/lib/models/Institute.class.php
+++ b/lib/models/Institute.class.php
@@ -41,6 +41,87 @@
 
 class Institute extends SimpleORMap implements Range
 {
+    protected static function configure($config = [])
+    {
+        $config['db_table'] = 'Institute';
+        $config['additional_fields']['is_fak']['get'] = 'isFaculty';
+
+        $config['has_many']['members'] = [
+            'class_name' => InstituteMember::class,
+            'assoc_func' => 'findByInstitute',
+            'on_delete' => 'delete',
+            'on_store' => 'store',
+        ];
+        $config['has_many']['home_courses'] = [
+            'class_name' => Course::class,
+            'on_delete' => 'delete',
+            'on_store' => 'store',
+        ];
+        $config['has_many']['sub_institutes'] = [
+            'class_name' => Institute::class,
+            'assoc_foreign_key' => 'fakultaets_id',
+            'assoc_func' => 'findByFaculty',
+            'on_delete' => 'delete',
+            'on_store' => 'store',
+        ];
+        $config['has_many']['datafields'] = [
+            'class_name' => DatafieldEntryModel::class,
+            'assoc_foreign_key' =>
+                function($model,$params) {
+                    $model->setValue('range_id', $params[0]->id);
+                },
+            'assoc_func' => 'findByModel',
+            'on_delete' => 'delete',
+            'on_store' => 'store',
+            'foreign_key' =>
+                function($i) {
+                    return [$i];
+                }
+        ];
+        $config['belongs_to']['faculty'] = [
+            'class_name' => Institute::class,
+            'foreign_key' => 'fakultaets_id',
+        ];
+        $config['has_and_belongs_to_many']['courses'] = [
+            'class_name' => Course::class,
+            'thru_table' => 'seminar_inst',
+            'on_delete' => 'delete',
+            'on_store' => 'store',
+        ];
+        $config['has_many']['scm'] = [
+            'class_name'        => StudipScmEntry::class,
+            'assoc_foreign_key' => 'range_id',
+            'on_delete'         => 'delete',
+            'on_store'          => 'store',
+        ];
+        $config['has_many']['status_groups'] = [
+            'class_name'        => Statusgruppen::class,
+            'assoc_foreign_key' => 'range_id',
+            'on_delete'         => 'delete',
+            'on_store'          => 'store',
+            'order_by'          => 'ORDER BY position ASC',
+        ];
+        $config['has_many']['blubberthreads'] = [
+            'class_name' => BlubberThread::class,
+            'assoc_func' => 'findByInstitut',
+            'on_delete'  => 'delete',
+            'on_store'   => 'store',
+        ];
+        $config['has_many']['tools'] = [
+            'class_name'        => ToolActivation::class,
+            'assoc_foreign_key' => 'range_id',
+            'order_by'          => 'ORDER BY position',
+            'on_delete'         => 'delete',
+        ];
+        $config['additional_fields']['all_status_groups']['get'] = function ($institute) {
+            return Statusgruppen::findAllByRangeId($institute->id, true);
+        };
+
+        $config['i18n_fields']['name'] = true;
+        $config['registered_callbacks']['after_create'][] = 'setDefaultTools';
+
+        parent::configure($config);
+    }
 
     /**
     * Returns the currently active course or false if none is active.
@@ -60,7 +141,7 @@ class Institute extends SimpleORMap implements Range
      * @param string $fakultaets_id
      * @return array
      */
-    static function findByFaculty($fakultaets_id)
+    public static function findByFaculty($fakultaets_id)
     {
         return self::findBySQL("fakultaets_id=? AND fakultaets_id <> institut_id ORDER BY Name ASC", [$fakultaets_id]);
     }
@@ -69,7 +150,7 @@ class Institute extends SimpleORMap implements Range
      * returns an array of all institutes ordered by faculties and name
      * @return array
      */
-    static function getInstitutes()
+    public static function getInstitutes()
     {
         $db = DBManager::get();
         $result = $db->query("SELECT Institute.Institut_id, Institute.Name, IF(Institute.Institut_id=Institute.fakultaets_id,1,0) AS is_fak " .
@@ -82,10 +163,12 @@ class Institute extends SimpleORMap implements Range
     /**
      * returns an array of all institutes to which the given user belongs,
      * ordered by faculties and name. The user role for each institute is included
+     *
      * @param string $user_id if omitted, the current user is used
+     *
      * @return array
      */
-    static function getMyInstitutes($user_id = NULL)
+    public static function getMyInstitutes($user_id = NULL)
     {
         global $perm, $user;
         if (!$user_id) {
@@ -125,94 +208,9 @@ class Institute extends SimpleORMap implements Range
         return $result;
     }
 
-    /**
-     *
-     */
-    protected static function configure($config = [])
-    {
-        $config['db_table'] = 'Institute';
-        $config['additional_fields']['is_fak']['get'] = 'isFaculty';
-
-        $config['has_many']['members'] = [
-            'class_name' => 'InstituteMember',
-            'assoc_func' => 'findByInstitute',
-            'on_delete' => 'delete',
-            'on_store' => 'store',
-        ];
-        $config['has_many']['home_courses'] = [
-            'class_name' => 'Course',
-            'on_delete' => 'delete',
-            'on_store' => 'store',
-        ];
-        $config['has_many']['sub_institutes'] = [
-            'class_name' => 'Institute',
-            'assoc_foreign_key' => 'fakultaets_id',
-            'assoc_func' => 'findByFaculty',
-            'on_delete' => 'delete',
-            'on_store' => 'store',
-        ];
-        $config['has_many']['datafields'] = [
-            'class_name' => 'DatafieldEntryModel',
-            'assoc_foreign_key' =>
-                function($model,$params) {
-                    $model->setValue('range_id', $params[0]->id);
-                },
-            'assoc_func' => 'findByModel',
-            'on_delete' => 'delete',
-            'on_store' => 'store',
-            'foreign_key' =>
-                function($i) {
-                    return [$i];
-                }
-        ];
-        $config['belongs_to']['faculty'] = [
-            'class_name' => 'Institute',
-            'foreign_key' => 'fakultaets_id',
-        ];
-        $config['has_and_belongs_to_many']['courses'] = [
-            'class_name' => 'Course',
-            'thru_table' => 'seminar_inst',
-            'on_delete' => 'delete',
-            'on_store' => 'store',
-        ];
-        $config['has_many']['scm'] = [
-            'class_name'        => 'StudipScmEntry',
-            'assoc_foreign_key' => 'range_id',
-            'on_delete'         => 'delete',
-            'on_store'          => 'store',
-        ];
-        $config['has_many']['status_groups'] = [
-            'class_name'        => 'Statusgruppen',
-            'assoc_foreign_key' => 'range_id',
-            'on_delete'         => 'delete',
-            'on_store'          => 'store',
-            'order_by'          => 'ORDER BY position ASC',
-        ];
-        $config['has_many']['blubberthreads'] = [
-            'class_name' => 'BlubberThread',
-            'assoc_func' => 'findByInstitut',
-            'on_delete'  => 'delete',
-            'on_store'   => 'store',
-        ];
-        $config['has_many']['tools'] = [
-            'class_name'        => 'ToolActivation',
-            'assoc_foreign_key' => 'range_id',
-            'order_by'          => 'ORDER BY position',
-            'on_delete'         => 'delete'
-        ];
-        $config['additional_fields']['all_status_groups']['get'] = function ($institute) {
-            return Statusgruppen::findAllByRangeId($institute->id, true);
-        };
-
-        $config['i18n_fields']['name'] = true;
-        $config['registered_callbacks']['after_create'][] = 'setDefaultTools';
-
-        parent::configure($config);
-    }
-
-    function isFaculty()
+    public function isFaculty()
     {
-        return $this->fakultaets_id == $this->institut_id;
+        return $this->fakultaets_id === $this->institut_id;
     }
 
     /**
@@ -221,7 +219,8 @@ class Institute extends SimpleORMap implements Range
      * @param string formatting template name
      * @return string Fullname
      */
-    public function getFullname($format = 'default') {
+    public function getFullname($format = 'default'): string
+    {
         $template['type-name'] = '%2$s: %1$s';
         if ($format === 'default' || !isset($template[$format])) {
            $format = 'type-name';
@@ -240,7 +239,7 @@ class Institute extends SimpleORMap implements Range
      *
      * @return string
      */
-    public function describeRange()
+    public function describeRange(): string
     {
         return _('Einrichtung');
     }
@@ -250,7 +249,7 @@ class Institute extends SimpleORMap implements Range
      *
      * @return string
      */
-    public function getRangeType()
+    public function getRangeType(): string
     {
         return 'institute';
     }
@@ -280,7 +279,7 @@ class Institute extends SimpleORMap implements Range
      * @return bool
      * @todo Check permissions
      */
-    public function isAccessibleToUser($user_id = null)
+    public function isAccessibleToUser($user_id = null): bool
     {
         return true;
     }
@@ -292,7 +291,7 @@ class Institute extends SimpleORMap implements Range
      * @return bool
      * @todo Check permissions
      */
-    public function isEditableByUser($user_id = null)
+    public function isEditableByUser($user_id = null): bool
     {
         if ($user_id === null) {
             $user_id = $GLOBALS['user']->id;
@@ -332,7 +331,7 @@ class Institute extends SimpleORMap implements Range
      * @param $name string name of tool / plugin
      * @return bool
      */
-    public function isToolActive($name)
+    public function isToolActive($name): bool
     {
         $plugin = PluginEngine::getPlugin($name);
         return $plugin && $this->tools->findOneby('plugin_id', $plugin->getPluginId());
diff --git a/lib/models/StatusgruppeUser.php b/lib/models/StatusgruppeUser.php
index cf0b85bc78872419e39fabe924501c092ff36eaf..04b42b6833d3d49f838b3b7c3cf57883806ae803 100644
--- a/lib/models/StatusgruppeUser.php
+++ b/lib/models/StatusgruppeUser.php
@@ -30,11 +30,11 @@ class StatusgruppeUser extends SimpleORMap implements PrivacyObject
     {
         $config['db_table'] = 'statusgruppe_user';
         $config['belongs_to']['group'] = [
-            'class_name' => 'Statusgruppen',
+            'class_name' => Statusgruppen::class,
             'foreign_key' => 'statusgruppe_id',
         ];
         $config['belongs_to']['user'] = [
-            'class_name' => 'User',
+            'class_name' => User::class,
             'foreign_key' => 'user_id',
         ];
 
diff --git a/lib/models/Statusgruppen.php b/lib/models/Statusgruppen.php
index 1c0927e7064073b8a92199109ccaf0196737205d..16cd3d786965c41e3252e79cdd65d28e3853a073 100644
--- a/lib/models/Statusgruppen.php
+++ b/lib/models/Statusgruppen.php
@@ -33,6 +33,9 @@
  * @property string children computed column
  * @property SimpleORMapCollection members has_many StatusgruppeUser
  * @property Statusgruppen parent belongs_to Statusgruppen
+ * @property Course course belongs_to course
+ * @property Institute institute belongs_to institute
+ * @property User user belongs_to user
  */
 class Statusgruppen extends SimpleORMap implements PrivacyObject
 {
@@ -42,36 +45,36 @@ class Statusgruppen extends SimpleORMap implements PrivacyObject
     {
         $config['db_table'] = 'statusgruppen';
         $config['has_many']['members'] = [
-            'class_name'        => 'StatusgruppeUser',
+            'class_name'        => StatusgruppeUser::class,
             'assoc_foreign_key' => 'statusgruppe_id',
             'on_delete'         => 'delete',
             'order_by'          => 'ORDER BY position ASC',
         ];
         $config['has_and_belongs_to_many']['dates'] = [
-            'class_name' => 'CourseDate',
+            'class_name' => CourseDate::class,
             'thru_table' => 'termin_related_groups',
             'order_by'   => 'ORDER BY date',
             'on_delete'  => 'delete', // TODO: This might cause trouble
             'on_store'   => 'store'
         ];
         $config['belongs_to']['parent'] = [
-            'class_name'  => 'Statusgruppen',
+            'class_name'  => Statusgruppen::class,
             'foreign_key' => 'range_id',
         ];
         $config['belongs_to']['course'] = [
-            'class_name'  => 'Course',
+            'class_name'  => Course::class,
             'foreign_key' => 'range_id',
         ];
         $config['belongs_to']['institute'] = [
-            'class_name'  => 'Institute',
+            'class_name'  => Institute::class,
             'foreign_key' => 'range_id',
         ];
         $config['belongs_to']['user'] = [
-            'class_name'  => 'User',
+            'class_name'  => User::class,
             'foreign_key' => 'range_id',
         ];
         $config['has_one']['blubberthread'] = [
-            'class_name' => 'BlubberStatusgruppeThread',
+            'class_name' => BlubberStatusgruppeThread::class,
             'on_store' => 'store',
             'on_delete' => 'delete'
         ];
diff --git a/lib/visual.inc.php b/lib/visual.inc.php
index ae1f9d89bfca4d8dbdfbe9a176a7dbc713d57ecb..303987d76fd30811294286246546779420a462f6 100644
--- a/lib/visual.inc.php
+++ b/lib/visual.inc.php
@@ -635,10 +635,10 @@ function tooltip2($text, $with_alt = TRUE, $with_popup = FALSE) {
  * @param bool $important render icon in "important" style
  * @param bool $html tooltip text is HTML content
  */
-function tooltipIcon($text, $important = false, $html = false)
+function tooltipIcon($text, $important = false, $html = false): string
 {
     if (!trim($text)) {
-        return;
+        return '';
     }
 
     // render tooltip
diff --git a/resources/assets/stylesheets/less/lists.less b/resources/assets/stylesheets/less/lists.less
index 4e10367050b891a350f7447ac0de7bb53d45e550..20ed99425bed65325e0794e884e4bc1a09f09604 100644
--- a/resources/assets/stylesheets/less/lists.less
+++ b/resources/assets/stylesheets/less/lists.less
@@ -48,6 +48,12 @@ ol {
             content: "";
         }
     }
+
+    &.narrow {
+        > li {
+            display: inline-flex;
+        }
+    }
 }
 .list-pipe-separated {
     .list-inline();