diff --git a/src/pretix/base/migrations/0265_itemcategory_cross_selling.py b/src/pretix/base/migrations/0265_itemcategory_cross_selling.py
new file mode 100644
index 0000000000..2601818c23
--- /dev/null
+++ b/src/pretix/base/migrations/0265_itemcategory_cross_selling.py
@@ -0,0 +1,31 @@
+# Generated by Django 4.2.11 on 2024-05-27 13:19
+
+from django.db import migrations, models
+import pretix.base.models.orders
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("pretixbase", "0264_order_internal_secret"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="itemcategory",
+ name="cross_selling_condition",
+ field=models.CharField(null=True),
+ ),
+ migrations.AddField(
+ model_name="itemcategory",
+ name="cross_selling_mode",
+ field=models.CharField(null=True),
+ ),
+ migrations.AddField(
+ model_name="itemcategory",
+ name="cross_selling_match_products",
+ field=models.ManyToManyField(
+ related_name="matched_by_cross_selling_categories", to="pretixbase.item"
+ ),
+ ),
+ ]
diff --git a/src/pretix/base/models/items.py b/src/pretix/base/models/items.py
index 1ad91ed540..15459d8b3b 100644
--- a/src/pretix/base/models/items.py
+++ b/src/pretix/base/models/items.py
@@ -158,6 +158,8 @@ class ItemCategory(LoggedModel):
name = self.internal_name or self.name
if self.is_addon:
return _('{category} (Add-On products)').format(category=str(name))
+ if self.cross_selling_mode is not None:
+ return _('{category} ({category_type})').format(category=str(name), category_type=self.get_cross_selling_mode_display())
return str(name)
def get_category_type_display(self):
diff --git a/src/pretix/control/templates/pretixcontrol/items/categories.html b/src/pretix/control/templates/pretixcontrol/items/categories.html
index 753f067a32..0078a2832e 100644
--- a/src/pretix/control/templates/pretixcontrol/items/categories.html
+++ b/src/pretix/control/templates/pretixcontrol/items/categories.html
@@ -31,6 +31,7 @@
@@ -40,6 +41,13 @@
{% trans "Product categories" %}
+ {% trans "Category type" %}