diff --git a/src/api/serializers.py b/src/api/serializers.py
index bbad60a25ca8a057c2da409cb7360f97f328f9af..e0a344ae4a481f727e1d5d525ca9f6a29684a07f 100644
--- a/src/api/serializers.py
+++ b/src/api/serializers.py
@@ -11,7 +11,6 @@ from core.models.assemblies import Assembly
 from core.models.badges import Badge, BadgeToken, BadgeTokenTimeConstraint
 from core.models.conference import Conference, ConferenceMember, ConferenceTrack
 from core.models.events import Event
-from core.models.links import Link
 from core.models.messages import DirectMessage
 from core.models.metanavi import MetaNavItem
 from core.models.rooms import Room
@@ -51,56 +50,6 @@ class ParameterisedHyperlinkedIdentityField(HyperlinkedIdentityField):
         return reverse(view_name, kwargs=kwargs, request=request, format=format)
 
 
-class HubHyperlinkedIdentityField(HyperlinkedIdentityField):
-    """
-    Represents the instance, or a property on the instance, using hyperlinking.
-
-    lookup_fields is a tuple of tuples of the form:
-        ('model_field', 'url_parameter')
-
-    taken from https://github.com/encode/django-rest-framework/issues/1024
-    """
-
-    lookup_fields = (('pk', 'pk'),)
-
-    def __init__(self, *args, **kwargs):
-        self.lookup_fields = kwargs.pop('lookup_fields', self.lookup_fields)
-        super().__init__(*args, **kwargs)
-
-    def get_url(self, obj, view_name, request, format):  # pylint: disable=redefined-builtin
-        """
-        Given an object, return the URL that hyperlinks to the object.
-
-        May raise a `NoReverseMatch` if the `view_name` and `lookup_field`
-        attributes are not configured to correctly match the URL conf.
-        """
-        kwargs = {}
-        for model_field, url_param in self.lookup_fields:
-            attr = obj
-            for field in model_field.split('.'):
-                attr = getattr(attr, field)
-            kwargs[url_param] = attr
-
-        from core.templatetags.hub_absolute import hub_absolute  # pylint: disable=import-outside-toplevel
-
-        # TODO: add request=request, format=format,
-        return hub_absolute(view_name, **kwargs, i18n=False)
-
-
-class LinkRelatedField(serializers.RelatedField):
-    """
-    A read only field that represents its targets using their
-    plain string representation.
-    """
-
-    def __init__(self, **kwargs):
-        kwargs['read_only'] = True
-        super().__init__(**kwargs)
-
-    def to_representation(self, value: Link):
-        return value.to_dict()
-
-
 class ValidatingModelSerializer(serializers.ModelSerializer):
     def validate(self, data):
         instance = self.Meta.model(**{field: value for field, value in data.items() if field in self.Meta.model._meta.fields})
@@ -268,20 +217,17 @@ class BadgeTokenUpdateSerializer(BadgeTokenSerializer):
 class RoomSerializer(HubModelSerializer):
     assembly = serializers.SlugRelatedField(read_only=True, slug_field='slug')
 
-    links = LinkRelatedField(
+    links = serializers.StringRelatedField(
         many=True,
         read_only=True,
     )
 
-    public_url = HubHyperlinkedIdentityField(view_name='plainui:room', lookup_fields=(('slug', 'slug'),))
-
     class Meta:
         model = Room
         read_only_fields = ['id']
         fields = [
             'id',
             'name',
-            'slug',
             'blocked',
             'room_type',
             'capacity',
@@ -289,7 +235,6 @@ class RoomSerializer(HubModelSerializer):
             'assembly',
             'links',
             'backend_link',
-            'public_url',
         ]
         staff_only_fields = ['blocked', 'backend_link']
 
diff --git a/src/api/views/rooms.py b/src/api/views/rooms.py
index 82c422a2d1478d65289a8e2f472bf33ad063005e..716e8795e55ec091a9b6322e0da51deab81d6445 100644
--- a/src/api/views/rooms.py
+++ b/src/api/views/rooms.py
@@ -14,7 +14,7 @@ class ConferenceRoomList(ConferenceSlugMixin, generics.ListAPIView):
     serializer_class = RoomSerializer
 
     def get_queryset(self, **kwargs):
-        return Room.objects.conference_accessible(conference=self.conference).order_by('official_room_order', 'name')
+        return Room.objects.conference_accessible(conference=self.conference).order_by('name')
 
 
 class ConferenceRoomDetail(ConferenceSlugMixin, generics.RetrieveAPIView):
diff --git a/src/backoffice/templates/backoffice/schedule_source-detail.html b/src/backoffice/templates/backoffice/schedule_source-detail.html
index ac55db261e5d5ae1c85e163e5d9af5eb09982be3..2122ae2de9557aecdc34277179b406c8cf5f687d 100644
--- a/src/backoffice/templates/backoffice/schedule_source-detail.html
+++ b/src/backoffice/templates/backoffice/schedule_source-detail.html
@@ -20,7 +20,7 @@
     </div>
     <div class="card-body">
       <p>
-        Assembly: <strong><a href="{% url 'backoffice:assembly-edit' pk=object.assembly.id %}">{{ object.assembly|default:"<em>WILDCARD</em>" }}</a></strong>
+        Assembly: <strong>{{ object.assembly|default:"<em>WILDCARD</em>" }}</strong>
       </p>
       <p>
         Type: <strong>{{ object.import_type }}</strong>
@@ -108,10 +108,8 @@
           {% for mapping in object.mappings.all %}
             <tr>
               <td>{{ mapping.get_mapping_type_display }}</td>
-              <td>{{ mapping.source_id|default:'-' }}</td>
-              <td>
-                <a href="{{ mapping.local_url }}">{{ mapping.local_id|default:'-' }}</a>
-              </td>
+              <td>{{ mapping.source_id|default:"-" }}</td>
+              <td>{{ mapping.local_id|default:"-" }}</td>
               <td>{{ mapping.skip|yesno }}</td>
               <td>&nbsp;</td>
             </tr>
diff --git a/src/backoffice/templates/backoffice/schedule_source_import-detail.html b/src/backoffice/templates/backoffice/schedule_source_import-detail.html
index ec3be03022ad3a310bf8c4ac15812b7502b0a77a..8b7e2c2597d29b28450036f892667917660171ba 100644
--- a/src/backoffice/templates/backoffice/schedule_source_import-detail.html
+++ b/src/backoffice/templates/backoffice/schedule_source_import-detail.html
@@ -95,7 +95,7 @@
                   {{ item.source_id|default:"-/-" }}
                 </td>
                 <td class="{% if item.action == "seen" %}text-muted{% elif item.action == "error" %}text-danger{% elif item.action == "missing" or item.action == "removed" %}text-warning{% elif item.action == "added" %}text-success{% endif %}">
-                  <a href="{{ item.local_url }}">{{ item.local_id|default:"-/-" }}</a>
+                  {{ item.local_id|default:"-/-" }}
                 </td>
               </tr>
             {% endfor %}
diff --git a/src/core/admin.py b/src/core/admin.py
index d9ee6d63023dc4ceef23e7dcd652ed3192127f44..8158cdcd2d8298de242c0e11d39fd529859fa8aa 100644
--- a/src/core/admin.py
+++ b/src/core/admin.py
@@ -750,11 +750,11 @@ class RoomShareAdmin(admin.ModelAdmin):
 
 
 class RoomAdmin(admin.ModelAdmin):
-    list_display = ['conference', 'assembly', 'name', 'room_type', 'blocked', 'official_room_order', 'id']
+    list_display = ['conference', 'assembly', 'name', 'room_type', 'blocked']
     list_display_links = ['name']
     list_filter = ['conference', 'room_type', 'backend_status', 'blocked', 'is_official', 'is_public_fahrplan']
     save_as = True
-    search_fields = ['assembly__name', 'name', 'slug', 'id']
+    search_fields = ['assembly__name', 'name', 'slug']
     inlines = [RoomLinkInline, RoomShareInline, TagsInline]
     readonly_fields = ['id', 'occupants', 'reserve_capacity']
     ordering = ('-conference__id', F('assembly__is_official').desc(nulls_last=True), 'assembly__name', F('capacity').desc(nulls_last=True), 'name')
diff --git a/src/core/models/links.py b/src/core/models/links.py
index 65ded766dd94077ea2e2c23e69fe18d70a3f5a38..86764e7e409e67adef65819949d2b20d5600766f 100644
--- a/src/core/models/links.py
+++ b/src/core/models/links.py
@@ -5,7 +5,7 @@ from django.core.validators import URLValidator
 from django.db import models
 from django.utils.translation import gettext_lazy as _
 
-from core.utils import resolve_internal_url, resolve_link
+from core.utils import resolve_link
 
 
 class Link(models.Model):
@@ -62,14 +62,6 @@ class Link(models.Model):
             except ValidationError:
                 raise ValidationError({'link': _('Link__link__must_be_url')})
 
-    def to_dict(self):
-        return {
-            'type': self.link_type,
-            'name': self.name,
-            'uri': self.link,
-            'url': resolve_internal_url(self.link),
-        }
-
     def __str__(self) -> str:
         return self.name
 
diff --git a/src/core/models/rooms.py b/src/core/models/rooms.py
index cef75f46a77b2b89f46a675ac1a6e2c22217d303..b54819c259eb740fe27d5810a9ede9ef16a73cac 100644
--- a/src/core/models/rooms.py
+++ b/src/core/models/rooms.py
@@ -273,11 +273,6 @@ class Room(BackendMixin, models.Model):
             return link.link
         return None
 
-    def get_absolute_url(self):
-        from core.templatetags.hub_absolute import hub_absolute  # pylint: disable=import-outside-toplevel
-
-        return hub_absolute('plainui:room', slug=self.slug, i18n=settings.ARCHIVE_MODE)
-
     def __create_slug(self, extension='', max_length: int = 50):
         """
         recursive function to generate a free room slug based on the room name
@@ -506,13 +501,5 @@ class RoomLink(models.Model):
             if not resolve_internal_url(self.link, fallback_as_is=False):
                 raise ValidationError({'link': _('RoomLink__link__must_be_url')})
 
-    def to_dict(self):
-        return {
-            'type': self.link_type,
-            'name': self.name,
-            'uri': self.link,
-            'url': resolve_internal_url(self.link),
-        }
-
     def __str__(self):
         return self.name
diff --git a/src/core/models/schedules.py b/src/core/models/schedules.py
index e9245a6fff58b973224c68ca2defedf3cc27e73f..aed616a497c2659faa6e4b1bf292f6dd723c06bc 100644
--- a/src/core/models/schedules.py
+++ b/src/core/models/schedules.py
@@ -348,9 +348,6 @@ class ScheduleSource(models.Model):
                 )
                 logging.exception('Import on ScheduleSource %s encountered exception on creating mapping for %s "%s".', self.pk, item_type, item_source_id)
 
-                # ... and delete the incomplete (wrong) mapping if it was created
-                if new_mapping:
-                    mapping.delete()
                 return 'error'
 
             else:
@@ -430,7 +427,7 @@ class ScheduleSource(models.Model):
         allow_track = cfg.get('import_tracks') or False
 
         # note down all existing rooms, events and speakers so that we can call out the missing ones
-        if self.assembly and cfg.get('missing_rooms') != 'ignore':
+        if self.assembly:
             expected_rooms = list(self.assembly.rooms.values_list('id', flat=True))
         else:
             expected_rooms = list(
@@ -693,18 +690,6 @@ class ScheduleSourceMapping(models.Model):
         # we don't know about that mapping type, bail out
         raise LocalObjectAccessViolation('Unknown mapping.')
 
-    @property
-    def local_url(self):
-        if self.mapping_type == self.MappingType.ROOM:
-            return Room.admin_url(self.local_id)
-
-        if self.mapping_type == self.MappingType.EVENT:
-            return Event.admin_url(self.local_id)
-        if self.mapping_type == self.MappingType.SPEAKER:
-            return ''
-
-        return ''
-
     @property
     def local_object(self):
         if self._local_object is None:
@@ -839,13 +824,17 @@ class ScheduleSourceImport(models.Model):
                 # create list of unique errors for summary
                 msgs = list({x['message'].split('\n')[0] for x in errors})
 
-            stats = {t: sum(1 for x in activity if x['action'] == t) for t in ['added', 'changed', 'seen', 'deleted', 'missing', 'error', 'skipped']}
-            stats_str = ', '.join([f'{v}={k}' for (k, v) in stats.items() if v]) + ' \n' + ' \n'.join(msgs)
-            self.summary = f"{data.get('version') or ''}\nDONE: {stats_str}"[:200]
+            stats = (
+                ', '.join(
+                    (t + '=' + str(sum(1 for x in activity if x['action'] == t)))
+                    for t in ['added', 'changed', 'seen', 'deleted', 'missing', 'error', 'skipped']
+                )
+                + ' \n'
+                + ' \n'.join(msgs)
+            )
+            self.summary = f"{data.get('version') or ''}\nDONE: {stats}"[:200]
 
-            # add debug option to disable abort feature, as it might hide the actual error messages
-            if len(errors) > len(activity) / 2 and self.import_configuration.get('debug') is not True:
-                self.save(update_fields=['summary'])
+            if len(errors) > len(activity) / 2:
                 raise Exception('Too many errors, aborting import: ' + stats)
 
             self.save(update_fields=['data', 'summary'])
diff --git a/src/core/models/shared.py b/src/core/models/shared.py
index 967c37ee60402d618d187cd832c8a2f91aefce67..77d69925df55fca9553719454a82412b1a4070de 100644
--- a/src/core/models/shared.py
+++ b/src/core/models/shared.py
@@ -3,12 +3,6 @@ from django.utils.translation import gettext_lazy as _
 
 
 class BackendMixin(models.Model):
-    @classmethod
-    def admin_url(cls, pk):
-        from django.urls import reverse
-
-        return reverse(f'admin:{cls._meta.app_label}_{cls._meta.model_name}_change', args=[pk])
-
     class Meta:
         abstract = True