diff --git a/backend/conferences/migrations/0048_remove_conference_grants_default_accommodation_amount_and_more.py b/backend/conferences/migrations/0048_remove_conference_grants_default_accommodation_amount_and_more.py
new file mode 100644
index 0000000000..a7a9b93e5f
--- /dev/null
+++ b/backend/conferences/migrations/0048_remove_conference_grants_default_accommodation_amount_and_more.py
@@ -0,0 +1,32 @@
+# Generated by Django 5.0.8 on 2024-10-12 18:50
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("conferences", "0047_alter_conferencevoucher_options_and_more"),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name="conference",
+            name="grants_default_accommodation_amount",
+        ),
+        migrations.RemoveField(
+            model_name="conference",
+            name="grants_default_ticket_amount",
+        ),
+        migrations.RemoveField(
+            model_name="conference",
+            name="grants_default_travel_from_europe_amount",
+        ),
+        migrations.RemoveField(
+            model_name="conference",
+            name="grants_default_travel_from_extra_eu_amount",
+        ),
+        migrations.RemoveField(
+            model_name="conference",
+            name="grants_default_travel_from_italy_amount",
+        ),
+    ]
diff --git a/backend/conferences/models/conference.py b/backend/conferences/models/conference.py
index 9d39378dc5..a4a75d13dd 100644
--- a/backend/conferences/models/conference.py
+++ b/backend/conferences/models/conference.py
@@ -99,47 +99,6 @@ class Conference(GeoLocalizedModel, TimeFramedModel, TimeStampedModel):
         default="",
     )
 
-    grants_default_ticket_amount = models.DecimalField(
-        verbose_name=_("grants default ticket amount"),
-        null=True,
-        blank=True,
-        max_digits=6,
-        decimal_places=2,
-        default=None,
-    )
-    grants_default_accommodation_amount = models.DecimalField(
-        verbose_name=_("grants default accommodation amount"),
-        null=True,
-        blank=True,
-        max_digits=6,
-        decimal_places=2,
-        default=None,
-    )
-    grants_default_travel_from_italy_amount = models.DecimalField(
-        verbose_name=_("grants default travel from Italy amount"),
-        null=True,
-        blank=True,
-        max_digits=6,
-        decimal_places=2,
-        default=None,
-    )
-    grants_default_travel_from_europe_amount = models.DecimalField(
-        verbose_name=_("grants default travel from Europe amount"),
-        null=True,
-        blank=True,
-        max_digits=6,
-        decimal_places=2,
-        default=None,
-    )
-    grants_default_travel_from_extra_eu_amount = models.DecimalField(
-        verbose_name=_("grants default travel from Extra EU amount"),
-        null=True,
-        blank=True,
-        max_digits=6,
-        decimal_places=2,
-        default=None,
-    )
-
     video_title_template = models.TextField(
         default="",
         blank=True,
diff --git a/backend/grants/admin.py b/backend/grants/admin.py
index 81986604ee..2760256b0f 100644
--- a/backend/grants/admin.py
+++ b/backend/grants/admin.py
@@ -23,7 +23,7 @@
 from pretix import create_voucher
 from schedule.models import ScheduleItem
 from submissions.models import Submission
-from .models import Grant
+from .models import Grant, AidCategory, CountryAidAmount, GrantAllocation
 from django.db.models import Exists, OuterRef
 
 from django.contrib.admin import SimpleListFilter
@@ -150,31 +150,6 @@ class Meta:
         export_order = EXPORT_GRANTS_FIELDS
 
 
-def _check_amounts_are_not_empty(grant: Grant, request):
-    if grant.total_amount is None:
-        messages.error(
-            request,
-            f"Grant for {grant.name} is missing 'Total Amount'!",
-        )
-        return False
-
-    if grant.has_approved_accommodation() and grant.accommodation_amount is None:
-        messages.error(
-            request,
-            f"Grant for {grant.name} is missing 'Accommodation Amount'!",
-        )
-        return False
-
-    if grant.has_approved_travel() and grant.travel_amount is None:
-        messages.error(
-            request,
-            f"Grant for {grant.name} is missing 'Travel Amount'!",
-        )
-        return False
-
-    return True
-
-
 @admin.action(description="Send Approved/Waiting List/Rejected reply emails")
 @validate_single_conference_selection
 def send_reply_emails(modeladmin, request, queryset):
@@ -195,16 +170,6 @@ def send_reply_emails(modeladmin, request, queryset):
 
     for grant in queryset:
         if grant.status in (Grant.Status.approved,):
-            if grant.approved_type is None:
-                messages.error(
-                    request,
-                    f"Grant for {grant.name} is missing 'Grant Approved Type'!",
-                )
-                return
-
-            if not _check_amounts_are_not_empty(grant, request):
-                return
-
             now = timezone.now()
             grant.applicant_reply_deadline = timezone.datetime(
                 now.year, now.month, now.day, 23, 59, 59, tzinfo=UTC
@@ -242,8 +207,6 @@ def send_grant_reminder_to_waiting_for_confirmation(modeladmin, request, queryse
             )
             return
 
-        _check_amounts_are_not_empty(grant, request)
-
         send_grant_reply_approved_email.delay(grant_id=grant.id, is_reminder=True)
 
         messages.info(request, f"Grant reminder sent to {grant.name}")
@@ -348,11 +311,6 @@ class Meta:
             "id",
             "name",
             "status",
-            "approved_type",
-            "ticket_amount",
-            "travel_amount",
-            "accommodation_amount",
-            "total_amount",
             "full_name",
             "conference",
             "user",
@@ -367,7 +325,6 @@ class Meta:
             "why",
             "notes",
             "travelling_from",
-            "country_type",
             "applicant_reply_sent_at",
             "applicant_reply_deadline",
         )
@@ -405,6 +362,53 @@ def queryset(self, request, queryset):
         return queryset
 
 
+@admin.register(AidCategory)
+class AidCategoryAdmin(admin.ModelAdmin):
+    list_display = (
+        "name",
+        "conference",
+        "category",
+        "max_amount",
+        "included_by_default",
+    )
+
+    list_filter = ("conference", "category")
+    search_fields = ("name", "description", "conference", "max_amount")
+
+
+@admin.register(CountryAidAmount)
+class CountryAidAmountAdmin(admin.ModelAdmin):
+    list_display = ("conference", "_country", "max_amount")
+
+    def _country(self, obj):
+        if obj.country:
+            country = countries.get(code=obj.country)
+            if country:
+                return f"{country.name} {country.emoji}"
+
+        return ""
+
+
+class GrantAllocationFormSet:
+    pass
+
+
+class GrantAllocationInline(admin.StackedInline):
+    model = GrantAllocation
+
+    def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
+        if db_field.name == "category":
+            grant_id = request.resolver_match.kwargs.get("object_id")
+            if grant_id:
+                grant = Grant.objects.get(pk=grant_id)
+                kwargs["queryset"] = AidCategory.objects.filter(
+                    conference=grant.conference
+                )
+            else:
+                kwargs["queryset"] = AidCategory.objects.none()
+        return super().formfield_for_foreignkey(db_field, request, **kwargs)
+
+
 @admin.register(Grant)
 class GrantAdmin(ExportMixin, ConferencePermissionMixin, admin.ModelAdmin):
     change_list_template = "admin/grants/grant/change_list.html"
@@ -418,12 +422,6 @@ class GrantAdmin(ExportMixin, ConferencePermissionMixin, admin.ModelAdmin):
         "emoji_gender",
         "conference",
         "status",
-        "approved_type",
-        "ticket_amount",
-        "travel_amount",
-        "accommodation_amount",
-        "total_amount",
-        "country_type",
         "applicant_reply_sent_at",
         "applicant_reply_deadline",
         "voucher_code",
@@ -433,9 +431,7 @@ class GrantAdmin(ExportMixin, ConferencePermissionMixin, admin.ModelAdmin):
     list_filter = (
         "conference",
         "status",
-        "country_type",
         "occupation",
-        "approved_type",
         "interested_in_volunteering",
         "needs_funds_for_travel",
         "need_visa",
@@ -447,6 +443,7 @@ class GrantAdmin(ExportMixin, ConferencePermissionMixin, admin.ModelAdmin):
     )
     search_fields = (
         "email",
+        "name",
         "full_name",
         "travelling_from",
         "been_to_other_events",
@@ -470,12 +467,6 @@ class GrantAdmin(ExportMixin, ConferencePermissionMixin, admin.ModelAdmin):
             {
                 "fields": (
                     "status",
-                    "approved_type",
-                    "country_type",
-                    "ticket_amount",
-                    "travel_amount",
-                    "accommodation_amount",
-                    "total_amount",
                     "applicant_reply_sent_at",
                     "applicant_reply_deadline",
                     "pretix_voucher_id",
@@ -523,6 +514,7 @@ class GrantAdmin(ExportMixin, ConferencePermissionMixin, admin.ModelAdmin):
             },
         ),
     )
+    inlines = [GrantAllocationInline]
 
     @admin.display(description="User", ordering="user__full_name")
     def user_display_name(self, obj):
diff --git a/backend/grants/migrations/0021_remove_grant_accommodation_amount_and_more.py b/backend/grants/migrations/0021_remove_grant_accommodation_amount_and_more.py
new file mode 100644
index 0000000000..19a5d076b6
--- /dev/null
+++ b/backend/grants/migrations/0021_remove_grant_accommodation_amount_and_more.py
@@ -0,0 +1,425 @@
+# Generated by Django 5.0.8 on 2024-10-12 18:50
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        (
+            "conferences",
+            "0048_remove_conference_grants_default_accommodation_amount_and_more",
+        ),
+        ("grants", "0020_remove_grant_applicant_message_and_more"),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name="grant",
+            name="accommodation_amount",
+        ),
+        migrations.RemoveField(
+            model_name="grant",
+            name="approved_type",
+        ),
+        migrations.RemoveField(
+            model_name="grant",
+            name="country_type",
+        ),
+        migrations.RemoveField(
+            model_name="grant",
+            name="ticket_amount",
+        ),
+        migrations.RemoveField(
+            model_name="grant",
+            name="total_amount",
+        ),
+        migrations.RemoveField(
+            model_name="grant",
+            name="travel_amount",
+        ),
+        migrations.CreateModel(
+            name="AidCategory",
+            fields=[
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("name", models.CharField(max_length=100)),
+                ("description", models.TextField(blank=True, null=True)),
+                (
+                    "max_amount",
+                    models.DecimalField(
+                        decimal_places=0,
+                        help_text="Maximum amount for this category",
+                        max_digits=6,
+                    ),
+                ),
+                (
+                    "category",
+                    models.CharField(
+                        choices=[
+                            ("travel", "Travel"),
+                            ("ticket", "Ticket"),
+                            ("accommodation", "Accommodation"),
+                            ("other", "Other"),
+                        ],
+                        max_length=20,
+                    ),
+                ),
+                (
+                    "included_by_default",
+                    models.BooleanField(
+                        default=False,
+                        help_text="Automatically include this category in grants by default",
+                    ),
+                ),
+                (
+                    "conference",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="aid_categories",
+                        to="conferences.conference",
+                    ),
+                ),
+            ],
+        ),
+        migrations.CreateModel(
+            name="CountryAidAmount",
+            fields=[
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "country",
+                    models.CharField(
+                        blank=True,
+                        choices=[
+                            ("AF", "Afghanistan"),
+                            ("AL", "Albania"),
+                            ("DZ", "Algeria"),
+                            ("AS", "American Samoa"),
+                            ("AD", "Andorra"),
+                            ("AO", "Angola"),
+                            ("AI", "Anguilla"),
+                            ("AQ", "Antarctica"),
+                            ("AG", "Antigua and Barbuda"),
+                            ("AR", "Argentina"),
+                            ("AM", "Armenia"),
+                            ("AW", "Aruba"),
+                            ("AU", "Australia"),
+                            ("AT", "Austria"),
+                            ("AZ", "Azerbaijan"),
+                            ("BS", "Bahamas"),
+                            ("BH", "Bahrain"),
+                            ("BD", "Bangladesh"),
+                            ("BB", "Barbados"),
+                            ("BY", "Belarus"),
+                            ("BE", "Belgium"),
+                            ("BZ", "Belize"),
+                            ("BJ", "Benin"),
+                            ("BM", "Bermuda"),
+                            ("BT", "Bhutan"),
+                            ("BO", "Bolivia, Plurinational State of"),
+                            ("BQ", "Bonaire, Sint Eustatius and Saba"),
+                            ("BA", "Bosnia and Herzegovina"),
+                            ("BW", "Botswana"),
+                            ("BV", "Bouvet Island"),
+                            ("BR", "Brazil"),
+                            ("IO", "British Indian Ocean Territory"),
+                            ("BN", "Brunei Darussalam"),
+                            ("BG", "Bulgaria"),
+                            ("BF", "Burkina Faso"),
+                            ("BI", "Burundi"),
+                            ("CV", "Cabo Verde"),
+                            ("KH", "Cambodia"),
+                            ("CM", "Cameroon"),
+                            ("CA", "Canada"),
+                            ("KY", "Cayman Islands"),
+                            ("CF", "Central African Republic"),
+                            ("TD", "Chad"),
+                            ("CL", "Chile"),
+                            ("CN", "China"),
+                            ("CX", "Christmas Island"),
+                            ("CC", "Cocos (Keeling) Islands"),
+                            ("CO", "Colombia"),
+                            ("KM", "Comoros"),
+                            ("CG", "Congo"),
+                            ("CD", "Congo, The Democratic Republic of the"),
+                            ("CK", "Cook Islands"),
+                            ("CR", "Costa Rica"),
+                            ("HR", "Croatia"),
+                            ("CU", "Cuba"),
+                            ("CW", "Curaçao"),
+                            ("CY", "Cyprus"),
+                            ("CZ", "Czechia"),
+                            ("CI", "Côte d'Ivoire"),
+                            ("DK", "Denmark"),
+                            ("DJ", "Djibouti"),
+                            ("DM", "Dominica"),
+                            ("DO", "Dominican Republic"),
+                            ("EC", "Ecuador"),
+                            ("EG", "Egypt"),
+                            ("SV", "El Salvador"),
+                            ("GQ", "Equatorial Guinea"),
+                            ("ER", "Eritrea"),
+                            ("EE", "Estonia"),
+                            ("SZ", "Eswatini"),
+                            ("ET", "Ethiopia"),
+                            ("FK", "Falkland Islands (Malvinas)"),
+                            ("FO", "Faroe Islands"),
+                            ("FJ", "Fiji"),
+                            ("FI", "Finland"),
+                            ("FR", "France"),
+                            ("GF", "French Guiana"),
+                            ("PF", "French Polynesia"),
+                            ("TF", "French Southern Territories"),
+                            ("GA", "Gabon"),
+                            ("GM", "Gambia"),
+                            ("GE", "Georgia"),
+                            ("DE", "Germany"),
+                            ("GH", "Ghana"),
+                            ("GI", "Gibraltar"),
+                            ("GR", "Greece"),
+                            ("GL", "Greenland"),
+                            ("GD", "Grenada"),
+                            ("GP", "Guadeloupe"),
+                            ("GU", "Guam"),
+                            ("GT", "Guatemala"),
+                            ("GG", "Guernsey"),
+                            ("GN", "Guinea"),
+                            ("GW", "Guinea-Bissau"),
+                            ("GY", "Guyana"),
+                            ("HT", "Haiti"),
+                            ("HM", "Heard Island and McDonald Islands"),
+                            ("VA", "Holy See (Vatican City State)"),
+                            ("HN", "Honduras"),
+                            ("HK", "Hong Kong"),
+                            ("HU", "Hungary"),
+                            ("IS", "Iceland"),
+                            ("IN", "India"),
+                            ("ID", "Indonesia"),
+                            ("IR", "Iran, Islamic Republic of"),
+                            ("IQ", "Iraq"),
+                            ("IE", "Ireland"),
+                            ("IM", "Isle of Man"),
+                            ("IL", "Israel"),
+                            ("IT", "Italy"),
+                            ("JM", "Jamaica"),
+                            ("JP", "Japan"),
+                            ("JE", "Jersey"),
+                            ("JO", "Jordan"),
+                            ("KZ", "Kazakhstan"),
+                            ("KE", "Kenya"),
+                            ("KI", "Kiribati"),
+                            ("KP", "Korea, Democratic People's Republic of"),
+                            ("KR", "Korea, Republic of"),
+                            ("KW", "Kuwait"),
+                            ("KG", "Kyrgyzstan"),
+                            ("LA", "Lao People's Democratic Republic"),
+                            ("LV", "Latvia"),
+                            ("LB", "Lebanon"),
+                            ("LS", "Lesotho"),
+                            ("LR", "Liberia"),
+                            ("LY", "Libya"),
+                            ("LI", "Liechtenstein"),
+                            ("LT", "Lithuania"),
+                            ("LU", "Luxembourg"),
+                            ("MO", "Macao"),
+                            ("MG", "Madagascar"),
+                            ("MW", "Malawi"),
+                            ("MY", "Malaysia"),
+                            ("MV", "Maldives"),
+                            ("ML", "Mali"),
+                            ("MT", "Malta"),
+                            ("MH", "Marshall Islands"),
+                            ("MQ", "Martinique"),
+                            ("MR", "Mauritania"),
+                            ("MU", "Mauritius"),
+                            ("YT", "Mayotte"),
+                            ("MX", "Mexico"),
+                            ("FM", "Micronesia, Federated States of"),
+                            ("MD", "Moldova, Republic of"),
+                            ("MC", "Monaco"),
+                            ("MN", "Mongolia"),
+                            ("ME", "Montenegro"),
+                            ("MS", "Montserrat"),
+                            ("MA", "Morocco"),
+                            ("MZ", "Mozambique"),
+                            ("MM", "Myanmar"),
+                            ("NA", "Namibia"),
+                            ("NR", "Nauru"),
+                            ("NP", "Nepal"),
+                            ("NL", "Netherlands"),
+                            ("NC", "New Caledonia"),
+                            ("NZ", "New Zealand"),
+                            ("NI", "Nicaragua"),
+                            ("NE", "Niger"),
+                            ("NG", "Nigeria"),
+                            ("NU", "Niue"),
+                            ("NF", "Norfolk Island"),
+                            ("MK", "North Macedonia"),
+                            ("MP", "Northern Mariana Islands"),
+                            ("NO", "Norway"),
+                            ("OM", "Oman"),
+                            ("PK", "Pakistan"),
+                            ("PW", "Palau"),
+                            ("PS", "Palestine, State of"),
+                            ("PA", "Panama"),
+                            ("PG", "Papua New Guinea"),
+                            ("PY", "Paraguay"),
+                            ("PE", "Peru"),
+                            ("PH", "Philippines"),
+                            ("PN", "Pitcairn"),
+                            ("PL", "Poland"),
+                            ("PT", "Portugal"),
+                            ("PR", "Puerto Rico"),
+                            ("QA", "Qatar"),
+                            ("RO", "Romania"),
+                            ("RU", "Russian Federation"),
+                            ("RW", "Rwanda"),
+                            ("RE", "Réunion"),
+                            ("BL", "Saint Barthélemy"),
+                            ("SH", "Saint Helena, Ascension and Tristan da Cunha"),
+                            ("KN", "Saint Kitts and Nevis"),
+                            ("LC", "Saint Lucia"),
+                            ("MF", "Saint Martin (French part)"),
+                            ("PM", "Saint Pierre and Miquelon"),
+                            ("VC", "Saint Vincent and the Grenadines"),
+                            ("WS", "Samoa"),
+                            ("SM", "San Marino"),
+                            ("ST", "Sao Tome and Principe"),
+                            ("SA", "Saudi Arabia"),
+                            ("SN", "Senegal"),
+                            ("RS", "Serbia"),
+                            ("SC", "Seychelles"),
+                            ("SL", "Sierra Leone"),
+                            ("SG", "Singapore"),
+                            ("SX", "Sint Maarten (Dutch part)"),
+                            ("SK", "Slovakia"),
+                            ("SI", "Slovenia"),
+                            ("SB", "Solomon Islands"),
+                            ("SO", "Somalia"),
+                            ("ZA", "South Africa"),
+                            ("GS", "South Georgia and the South Sandwich Islands"),
+                            ("SS", "South Sudan"),
+                            ("ES", "Spain"),
+                            ("LK", "Sri Lanka"),
+                            ("SD", "Sudan"),
+                            ("SR", "Suriname"),
+                            ("SJ", "Svalbard and Jan Mayen"),
+                            ("SE", "Sweden"),
+                            ("CH", "Switzerland"),
+                            ("SY", "Syrian Arab Republic"),
+                            ("TW", "Taiwan, Province of China"),
+                            ("TJ", "Tajikistan"),
+                            ("TZ", "Tanzania, United Republic of"),
+                            ("TH", "Thailand"),
+                            ("TL", "Timor-Leste"),
+                            ("TG", "Togo"),
+                            ("TK", "Tokelau"),
+                            ("TO", "Tonga"),
+                            ("TT", "Trinidad and Tobago"),
+                            ("TN", "Tunisia"),
+                            ("TM", "Turkmenistan"),
+                            ("TC", "Turks and Caicos Islands"),
+                            ("TV", "Tuvalu"),
+                            ("TR", "Türkiye"),
+                            ("UG", "Uganda"),
+                            ("UA", "Ukraine"),
+                            ("AE", "United Arab Emirates"),
+                            ("GB", "United Kingdom"),
+                            ("US", "United States"),
+                            ("UM", "United States Minor Outlying Islands"),
+                            ("UY", "Uruguay"),
+                            ("UZ", "Uzbekistan"),
+                            ("VU", "Vanuatu"),
+                            ("VE", "Venezuela, Bolivarian Republic of"),
+                            ("VN", "Viet Nam"),
+                            ("VG", "Virgin Islands, British"),
+                            ("VI", "Virgin Islands, U.S."),
+                            ("WF", "Wallis and Futuna"),
+                            ("EH", "Western Sahara"),
+                            ("YE", "Yemen"),
+                            ("ZM", "Zambia"),
+                            ("ZW", "Zimbabwe"),
+                            ("AX", "Åland Islands"),
+                        ],
+                        null=True,
+                        verbose_name="Country",
+                    ),
+                ),
+                (
+                    "max_amount",
+                    models.DecimalField(
+                        decimal_places=0,
+                        help_text="Maximum amount for this category",
+                        max_digits=6,
+                    ),
+                ),
+                (
+                    "conference",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="travel_costs",
+                        to="conferences.conference",
+                    ),
+                ),
+            ],
+        ),
+        migrations.CreateModel(
+            name="GrantAllocation",
+            fields=[
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "allocated_amount",
+                    models.DecimalField(
+                        decimal_places=0,
+                        help_text="Actual amount allocated for this category",
+                        max_digits=6,
+                    ),
+                ),
+                (
+                    "category",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        to="grants.aidcategory",
+                    ),
+                ),
+                (
+                    "grant",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="allocations",
+                        to="grants.grant",
+                    ),
+                ),
+            ],
+        ),
+        migrations.AddField(
+            model_name="grant",
+            name="aid_categories",
+            field=models.ManyToManyField(
+                through="grants.GrantAllocation", to="grants.aidcategory"
+            ),
+        ),
+    ]
diff --git a/backend/grants/models.py b/backend/grants/models.py
index 111d47abf8..1b943beff0 100644
--- a/backend/grants/models.py
+++ b/backend/grants/models.py
@@ -14,6 +14,55 @@ def of_user(self, user):
         return self.filter(user=user)
 
 
+class AidCategory(models.Model):
+    class AidType(models.TextChoices):
+        TRAVEL = "travel", _("Travel")
+        TICKET = "ticket", _("Ticket")
+        ACCOMMODATION = "accommodation", _("Accommodation")
+        OTHER = "other", _("Other")
+
+    conference = models.ForeignKey(
+        "conferences.Conference",
+        on_delete=models.CASCADE,
+        related_name="aid_categories",
+    )
+    name = models.CharField(max_length=100)
+    description = models.TextField(blank=True, null=True)
+    max_amount = models.DecimalField(
+        max_digits=6, decimal_places=0, help_text=_("Maximum amount for this category")
+    )
+    category = models.CharField(max_length=20, choices=AidType.choices)
+    included_by_default = models.BooleanField(
+        default=False,
+        help_text="Automatically include this category in grants by default",
+    )
+
+    objects = GrantQuerySet().as_manager()
+
+    def __str__(self):
+        return f"{self.name} ({self.conference.name})"
+
+
+class CountryAidAmount(models.Model):
+    conference = models.ForeignKey(
+        "conferences.Conference", on_delete=models.CASCADE, related_name="travel_costs"
+    )
+    country = models.CharField(
+        "Country",
+        choices=[(country.code, country.name) for country in countries],
+        null=True,
+        blank=True,
+    )
+    max_amount = models.DecimalField(
+        max_digits=6, decimal_places=0, help_text=_("Maximum amount for this category")
+    )
+
+    objects = GrantQuerySet().as_manager()
+
+    def __str__(self):
+        return f"{self.country} ({self.conference.name}) - {self.max_amount}€"
+
+
 class Grant(TimeStampedModel):
     # TextChoices
     class Status(models.TextChoices):
@@ -37,11 +86,6 @@ class Status(models.TextChoices):
         Status.waiting_list_maybe.value,
     ]
 
-    class CountryType(models.TextChoices):
-        italy = "italy", _("Italy")
-        europe = "europe", _("Europe")
-        extra_eu = "extra_eu", _("Extra EU")
-
     class AgeGroup(models.TextChoices):
         range_less_than_10 = "range_less_than_10", _("10 years old or under")
         range_11_18 = "range_11_18", _("11 - 18 years old")
@@ -69,12 +113,6 @@ class InterestedInVolunteering(models.TextChoices):
         yes = "yes", _("Yes")
         absolutely = "absolutely", _("My soul is yours to take!")
 
-    class ApprovedType(models.TextChoices):
-        ticket_only = "ticket_only", _("Ticket Only")
-        ticket_travel = "ticket_travel", _("Ticket + Travel")
-        ticket_accommodation = "ticket_accommodation", _("Ticket + Accommodation")
-        ticket_travel_accommodation = "Ticket", _("Ticket + Travel + Accommodation")
-
     conference = models.ForeignKey(
         "conferences.Conference",
         on_delete=models.CASCADE,
@@ -143,51 +181,9 @@ class ApprovedType(models.TextChoices):
     status = models.CharField(
         _("status"), choices=Status.choices, max_length=30, default=Status.pending
     )
-    approved_type = models.CharField(
-        verbose_name=_("approved type"),
-        choices=ApprovedType.choices,
-        max_length=30,
-        blank=True,
-        null=True,
-    )
 
     # Financial amounts
-    ticket_amount = models.DecimalField(
-        verbose_name=_("ticket amount"),
-        null=True,
-        max_digits=6,
-        decimal_places=2,
-        default=0,
-    )
-    accommodation_amount = models.DecimalField(
-        verbose_name=_("accommodation amount"),
-        null=True,
-        max_digits=6,
-        decimal_places=2,
-        default=0,
-    )
-    travel_amount = models.DecimalField(
-        verbose_name=_("travel amount"),
-        null=True,
-        max_digits=6,
-        decimal_places=2,
-        default=0,
-    )
-    total_amount = models.DecimalField(
-        verbose_name=_("total amount"),
-        null=True,
-        max_digits=6,
-        decimal_places=2,
-        default=0,
-    )
-
-    country_type = models.CharField(
-        _("Country type"),
-        max_length=10,
-        choices=CountryType.choices,
-        null=True,
-        blank=True,
-    )
+    aid_categories = models.ManyToManyField(AidCategory, through="GrantAllocation")
 
     # Applicant Communication Tracking
     applicant_reply_sent_at = models.DateTimeField(
@@ -219,96 +215,9 @@ class ApprovedType(models.TextChoices):
 
     objects = GrantQuerySet().as_manager()
 
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self._original_status = self.status
-        self._original_approved_type = self.approved_type
-        self._original_country_type = self.country_type
-
     def __str__(self):
         return f"{self.full_name}"
 
-    def save(self, *args, **kwargs):
-        self._update_country_type()
-        self._calculate_grant_amounts()
-
-        update_fields = kwargs.get("update_fields", None)
-        if update_fields:
-            update_fields.append("total_amount")
-            update_fields.append("ticket_amount")
-            update_fields.append("accommodation_amount")
-            update_fields.append("travel_amount")
-            update_fields.append("country_type")
-
-        super().save(*args, **kwargs)
-
-        self._original_approved_type = self.approved_type
-        self._original_country_type = self.country_type
-        self._original_status = self.status
-
-    def _calculate_grant_amounts(self):
-        if self.status != Grant.Status.approved:
-            return
-
-        if (
-            self._original_status == self.status
-            and self._original_approved_type == self.approved_type
-            and self._original_country_type == self.country_type
-        ):
-            return
-
-        conference = self.conference
-        self.ticket_amount = conference.grants_default_ticket_amount or 0
-        self.accommodation_amount = 0
-        self.travel_amount = 0
-
-        default_accommodation_amount = (
-            conference.grants_default_accommodation_amount or 0
-        )
-        default_travel_from_italy_amount = (
-            conference.grants_default_travel_from_italy_amount or 0
-        )
-        default_travel_from_europe_amount = (
-            conference.grants_default_travel_from_europe_amount or 0
-        )
-        default_travel_from_extra_eu_amount = (
-            conference.grants_default_travel_from_extra_eu_amount or 0
-        )
-
-        if self.approved_type in (
-            Grant.ApprovedType.ticket_accommodation,
-            Grant.ApprovedType.ticket_travel_accommodation,
-        ):
-            self.accommodation_amount = default_accommodation_amount
-
-        if self.approved_type in (
-            Grant.ApprovedType.ticket_travel_accommodation,
-            Grant.ApprovedType.ticket_travel,
-        ):
-            if self.country_type == Grant.CountryType.italy:
-                self.travel_amount = default_travel_from_italy_amount
-            elif self.country_type == Grant.CountryType.europe:
-                self.travel_amount = default_travel_from_europe_amount
-            elif self.country_type == Grant.CountryType.extra_eu:
-                self.travel_amount = default_travel_from_extra_eu_amount
-
-        self.total_amount = (
-            self.ticket_amount + self.accommodation_amount + self.travel_amount
-        )
-
-    def _update_country_type(self):
-        if not self.travelling_from:
-            return
-
-        country = countries.get(code=self.travelling_from)
-        assert country
-        if country.code == "IT":
-            self.country_type = Grant.CountryType.italy
-        elif country.continent == "EU":
-            self.country_type = Grant.CountryType.europe
-        else:
-            self.country_type = Grant.CountryType.extra_eu
-
     def can_edit(self, user: User):
         return self.user_id == user.id
 
@@ -319,13 +228,26 @@ def get_admin_url(self):
         )
 
     def has_approved_travel(self):
-        return (
-            self.approved_type == Grant.ApprovedType.ticket_travel_accommodation
-            or self.approved_type == Grant.ApprovedType.ticket_travel
-        )
+        return self.aid_categories.filter(category=AidCategory.AidType.TRAVEL).exists()
 
     def has_approved_accommodation(self):
+        return self.aid_categories.filter(
+            category=AidCategory.AidType.ACCOMMODATION
+        ).exists()
+
+
+class GrantAllocation(models.Model):
+    grant = models.ForeignKey(
+        Grant, on_delete=models.CASCADE, related_name="allocations"
+    )
+    category = models.ForeignKey(AidCategory, on_delete=models.CASCADE)
+    allocated_amount = models.DecimalField(
+        max_digits=6,
+        decimal_places=0,
+        help_text="Actual amount allocated for this category",
+    )
+
+    def __str__(self):
         return (
-            self.approved_type == Grant.ApprovedType.ticket_accommodation
-            or self.approved_type == Grant.ApprovedType.ticket_travel_accommodation
+            f"{self.grant.full_name} - {self.category.name} - {self.allocated_amount}€"
         )
diff --git a/backend/grants/tasks.py b/backend/grants/tasks.py
index ba25eb6e8f..e68fee1a86 100644
--- a/backend/grants/tasks.py
+++ b/backend/grants/tasks.py
@@ -38,14 +38,6 @@ def send_grant_reply_approved_email(*, grant_id, is_reminder):
         "is_reminder": is_reminder,
     }
 
-    if grant.has_approved_travel():
-        if not grant.travel_amount:
-            raise ValueError(
-                "Grant travel amount is set to Zero, can't send the email!"
-            )
-
-        variables["travel_amount"] = f"{grant.travel_amount:.0f}"
-
     _new_send_grant_email(
         template_identifier=EmailTemplateIdentifier.grant_approved,
         grant=grant,
diff --git a/backend/grants/tests/factories.py b/backend/grants/tests/factories.py
index 7094b3a237..f07aa7c3c2 100644
--- a/backend/grants/tests/factories.py
+++ b/backend/grants/tests/factories.py
@@ -2,12 +2,33 @@
 from factory.django import DjangoModelFactory
 
 from conferences.tests.factories import ConferenceFactory
-from grants.models import Grant
+from grants.models import Grant, AidCategory, CountryAidAmount, GrantAllocation
 from helpers.constants import GENDERS
 from users.tests.factories import UserFactory
 from countries import countries
 
 
+class AidCategoryFactory(DjangoModelFactory):
+    class Meta:
+        model = AidCategory
+
+    name = factory.Faker("word")
+    description = factory.Faker("sentence")
+    conference = factory.SubFactory(ConferenceFactory)
+    max_amount = factory.fuzzy.FuzzyDecimal(50, 500)
+    category = factory.fuzzy.FuzzyChoice(AidCategory.AidType)
+    included_by_default = factory.Faker("boolean")
+
+
+class CountryAidAmountFactory(DjangoModelFactory):
+    class Meta:
+        model = CountryAidAmount
+
+    conference = factory.SubFactory(ConferenceFactory)
+    country = factory.fuzzy.FuzzyChoice([country.code for country in countries])
+    max_amount = factory.fuzzy.FuzzyDecimal(100, 1000)
+
+
 class GrantFactory(DjangoModelFactory):
     class Meta:
         model = Grant
@@ -36,3 +57,12 @@ class Meta:
     github_handle = factory.Faker("user_name")
     linkedin_url = factory.Faker("user_name")
     mastodon_handle = factory.Faker("user_name")
+
+
+class GrantAllocationFactory(DjangoModelFactory):
+    class Meta:
+        model = GrantAllocation
+
+    grant = factory.SubFactory(GrantFactory)
+    category = factory.SubFactory(AidCategoryFactory)
+    allocated_amount = factory.fuzzy.FuzzyDecimal(50, 500)
diff --git a/backend/grants/tests/test_admin.py b/backend/grants/tests/test_admin.py
index f72c2f329e..c3205dbd3f 100644
--- a/backend/grants/tests/test_admin.py
+++ b/backend/grants/tests/test_admin.py
@@ -61,7 +61,9 @@ def test_send_reply_emails_with_grants_from_multiple_conferences_fails(
 
 def test_send_reply_emails_approved_grant_missing_approved_type(rf, mocker):
     mock_messages = mocker.patch("grants.admin.messages")
-    grant = GrantFactory(status=Grant.Status.approved, approved_type=None)
+    grant = GrantFactory(
+        status=Grant.Status.approved,
+    )
     request = rf.get("/")
     mock_send_approved_email = mocker.patch(
         "grants.admin.send_grant_reply_approved_email.delay"
@@ -80,11 +82,7 @@ def test_send_reply_emails_approved_missing_amount(rf, mocker):
     mock_messages = mocker.patch("grants.admin.messages")
     grant = GrantFactory(
         status=Grant.Status.approved,
-        approved_type=Grant.ApprovedType.ticket_accommodation,
-        total_amount=None,
     )
-    grant.total_amount = None
-    grant.save()
     request = rf.get("/")
     mock_send_approved_email = mocker.patch(
         "grants.admin.send_grant_reply_approved_email.delay"
@@ -103,8 +101,6 @@ def test_send_reply_emails_approved_set_deadline_in_fourteen_days(rf, mocker):
     mock_messages = mocker.patch("grants.admin.messages")
     grant = GrantFactory(
         status=Grant.Status.approved,
-        approved_type=Grant.ApprovedType.ticket_accommodation,
-        total_amount=800,
     )
     request = rf.get("/")
     mock_send_approved_email = mocker.patch(
diff --git a/backend/grants/tests/test_models.py b/backend/grants/tests/test_models.py
index 2fc1001c86..3b6fd4aa30 100644
--- a/backend/grants/tests/test_models.py
+++ b/backend/grants/tests/test_models.py
@@ -1,162 +1,104 @@
-from grants.models import Grant
 from grants.tests.factories import GrantFactory
+from conferences.tests.factories import ConferenceFactory
 import pytest
 
+from grants.models import AidCategory
+from grants.models import GrantAllocation
+from grants.tests.factories import (
+    AidCategoryFactory,
+    CountryAidAmountFactory,
+    GrantAllocationFactory,
+)
 
 pytestmark = pytest.mark.django_db
 
 
-@pytest.mark.parametrize(
-    "data",
-    [
-        {
-            "approved_type": Grant.ApprovedType.ticket_travel,
-            "travelling_from": "IT",
-            "expected_ticket_amount": 100,
-            "expected_accommodation_amount": 0,
-            "expected_travel_amount": 300,
-        },
-        {
-            "approved_type": Grant.ApprovedType.ticket_only,
-            "travelling_from": "IT",
-            "expected_ticket_amount": 100,
-            "expected_accommodation_amount": 0,
-            "expected_travel_amount": 0,
-        },
-        {
-            "approved_type": Grant.ApprovedType.ticket_accommodation,
-            "travelling_from": "FR",
-            "expected_ticket_amount": 100,
-            "expected_accommodation_amount": 200,
-            "expected_travel_amount": 0,
-        },
-        {
-            "approved_type": Grant.ApprovedType.ticket_travel,
-            "travelling_from": "FR",
-            "expected_ticket_amount": 100,
-            "expected_accommodation_amount": 0,
-            "expected_travel_amount": 400,
-        },
-        {
-            "approved_type": Grant.ApprovedType.ticket_travel_accommodation,
-            "travelling_from": "AU",
-            "expected_ticket_amount": 100,
-            "expected_accommodation_amount": 200,
-            "expected_travel_amount": 500,
-        },
-    ],
-)
-def test_calculate_grant_amounts(data):
-    approved_type = data["approved_type"]
-    travelling_from = data["travelling_from"]
-    expected_ticket_amount = data["expected_ticket_amount"]
-    expected_accommodation_amount = data["expected_accommodation_amount"]
-    expected_travel_amount = data["expected_travel_amount"]
+def test_grant_with_default_aid_categories():
+    # Create an AidCategory that should be included by default
+    default_category = AidCategoryFactory(included_by_default=True)
 
-    grant = GrantFactory(
-        status=Grant.Status.pending,
-        approved_type=approved_type,
-        travelling_from=travelling_from,
-        conference__grants_default_ticket_amount=100,
-        conference__grants_default_accommodation_amount=200,
-        conference__grants_default_travel_from_italy_amount=300,
-        conference__grants_default_travel_from_europe_amount=400,
-        conference__grants_default_travel_from_extra_eu_amount=500,
-    )
+    # Create a Grant
+    grant = GrantFactory(conference=default_category.conference)
 
-    grant.status = Grant.Status.approved
-    grant.save()
+    # Ensure that the default AidCategory is included in the Grant's allocations
+    assert GrantAllocation.objects.filter(
+        grant=grant, category=default_category
+    ).exists()
 
-    grant.refresh_from_db()
 
-    assert grant.ticket_amount == expected_ticket_amount
-    assert grant.accommodation_amount == expected_accommodation_amount
-    assert grant.travel_amount == expected_travel_amount
-    assert (
-        grant.total_amount
-        == expected_ticket_amount
-        + expected_accommodation_amount
-        + expected_travel_amount
-    )
+def test_grant_travel_aid_calculation():
+    # Create a conference and country-specific travel cost
+    conference = ConferenceFactory()
+    country_aid = CountryAidAmountFactory(conference=conference, max_amount=300)
 
+    # Create a travel-related AidCategory
+    travel_category = AidCategoryFactory(
+        conference=conference, category=AidCategory.AidType.TRAVEL
+    )
 
-def test_resets_amounts_on_approved_type_change():
+    # Create a Grant with travelling_from matching the country aid
     grant = GrantFactory(
-        status=Grant.Status.pending,
-        approved_type=Grant.ApprovedType.ticket_only,
-        travelling_from="IT",
-        conference__grants_default_ticket_amount=100,
-        conference__grants_default_accommodation_amount=200,
-        conference__grants_default_travel_from_italy_amount=300,
-        conference__grants_default_travel_from_europe_amount=400,
-        conference__grants_default_travel_from_extra_eu_amount=500,
+        conference=conference,
+        travelling_from=country_aid.country,
+        needs_funds_for_travel=True,
     )
 
-    grant.status = Grant.Status.approved
+    # Trigger save to assign aid categories
     grant.save()
 
-    assert grant.ticket_amount == 100
-    assert grant.accommodation_amount == 0
-    assert grant.travel_amount == 0
-    assert grant.total_amount == 100
-
-    grant.approved_type = Grant.ApprovedType.ticket_travel_accommodation
-    grant.save()
+    # Check that the travel allocation is correctly calculated
+    travel_allocation = GrantAllocation.objects.get(
+        grant=grant, category=travel_category
+    )
+    assert travel_allocation.allocated_amount == country_aid.max_amount
 
-    assert grant.ticket_amount == 100
-    assert grant.accommodation_amount == 200
-    assert grant.travel_amount == 300
-    assert grant.total_amount == 600
 
+def test_grant_with_custom_allocated_amount():
+    # Create a custom AidCategory
+    custom_category = AidCategoryFactory(max_amount=400)
 
-def test_can_manually_change_amounts():
-    grant = GrantFactory(
-        status=Grant.Status.pending,
-        approved_type=Grant.ApprovedType.ticket_only,
-        travelling_from="IT",
-        conference__grants_default_ticket_amount=100,
-        conference__grants_default_accommodation_amount=200,
-        conference__grants_default_travel_from_italy_amount=300,
-        conference__grants_default_travel_from_europe_amount=400,
-        conference__grants_default_travel_from_extra_eu_amount=500,
+    # Create a Grant and manually allocate a custom amount
+    grant = GrantFactory()
+    allocation = GrantAllocationFactory(
+        grant=grant, category=custom_category, allocated_amount=350
     )
 
-    grant.status = Grant.Status.approved
-    grant.save(update_fields=["status"])
+    # Ensure that the allocation is correct
+    assert allocation.allocated_amount == 350
+    assert allocation.category == custom_category
+    assert allocation.grant == grant
 
-    assert grant.ticket_amount == 100
-    assert grant.accommodation_amount == 0
-    assert grant.travel_amount == 0
-    assert grant.total_amount == 100
 
-    grant.ticket_amount = 20
-    grant.accommodation_amount = 50
-    grant.travel_amount = 0
-    grant.total_amount = 70
-    grant.save()
+@pytest.mark.django_db
+def test_grant_has_approved_travel_true():
+    travel_category = AidCategoryFactory(category=AidCategory.AidType.TRAVEL)
+    grant = GrantFactory()
+    GrantAllocationFactory(grant=grant, category=travel_category)
 
-    assert grant.ticket_amount == 20
-    assert grant.accommodation_amount == 50
-    assert grant.travel_amount == 0
-    assert grant.total_amount == 70
+    # Test that has_approved_travel returns True
+    assert grant.has_approved_travel() is True
 
 
-@pytest.mark.parametrize(
-    "travelling_from,country_type",
-    [
-        ("IT", Grant.CountryType.italy),
-        ("FR", Grant.CountryType.europe),
-        ("AU", Grant.CountryType.extra_eu),
-        ("US", Grant.CountryType.extra_eu),
-    ],
-)
-def test_sets_country_type(travelling_from, country_type):
-    grant = GrantFactory(travelling_from=travelling_from)
+@pytest.mark.django_db
+def test_grant_has_approved_travel_false():
+    grant = GrantFactory()
+
+    assert grant.has_approved_travel() is False
+
+
+@pytest.mark.django_db
+def test_grant_has_approved_accommodation_true():
+    accommodation_category = AidCategoryFactory(
+        category=AidCategory.AidType.ACCOMMODATION
+    )
+    grant = GrantFactory()
+    GrantAllocationFactory(grant=grant, category=accommodation_category)
 
-    assert grant.country_type == country_type
+    assert grant.has_approved_accommodation() is True
 
 
-def test_sets_country_type_does_nothing_if_unset():
-    grant = GrantFactory(travelling_from=None)
+@pytest.mark.django_db
+def test_grant_has_approved_accommodation_false():
+    grant = GrantFactory()
 
-    assert grant.country_type is None
+    assert grant.has_approved_accommodation() is False
diff --git a/backend/grants/tests/test_tasks.py b/backend/grants/tests/test_tasks.py
index 7f8949b366..7e7172c71b 100644
--- a/backend/grants/tests/test_tasks.py
+++ b/backend/grants/tests/test_tasks.py
@@ -13,7 +13,6 @@
     send_grant_reply_rejected_email,
     send_grant_reply_waiting_list_email,
 )
-from grants.models import Grant
 
 pytestmark = pytest.mark.django_db
 
@@ -30,7 +29,6 @@ def test_send_grant_voucher_email(settings):
     grant = GrantFactory(
         user=user,
         voucher_code="ABC123",
-        approved_type=Grant.ApprovedType.ticket_only,
     )
 
     with patch("grants.tasks.EmailTemplate") as mock_email_template:
@@ -119,9 +117,7 @@ def test_handle_grant_reply_sent_reminder(settings):
     )
     grant = GrantFactory(
         conference=conference,
-        approved_type=Grant.ApprovedType.ticket_only,
         applicant_reply_deadline=datetime(2023, 2, 1, 23, 59, tzinfo=timezone.utc),
-        total_amount=680,
         user=user,
     )
 
@@ -162,9 +158,7 @@ def test_handle_grant_approved_ticket_travel_accommodation_reply_sent(settings):
 
     grant = GrantFactory(
         conference=conference,
-        approved_type=Grant.ApprovedType.ticket_travel_accommodation,
         applicant_reply_deadline=datetime(2023, 2, 1, 23, 59, tzinfo=timezone.utc),
-        travel_amount=680,
         user=user,
     )
 
@@ -208,9 +202,7 @@ def test_handle_grant_approved_ticket_travel_accommodation_fails_with_no_amount(
 
     grant = GrantFactory(
         conference=conference,
-        approved_type=Grant.ApprovedType.ticket_travel_accommodation,
         applicant_reply_deadline=datetime(2023, 2, 1, 23, 59, tzinfo=timezone.utc),
-        travel_amount=0,
         user=user,
     )
 
@@ -236,9 +228,7 @@ def test_handle_grant_approved_ticket_only_reply_sent(settings):
 
     grant = GrantFactory(
         conference=conference,
-        approved_type=Grant.ApprovedType.ticket_only,
         applicant_reply_deadline=datetime(2023, 2, 1, 23, 59, tzinfo=timezone.utc),
-        total_amount=680,
         user=user,
     )
 
@@ -279,10 +269,7 @@ def test_handle_grant_approved_travel_reply_sent(settings):
 
     grant = GrantFactory(
         conference=conference,
-        approved_type=Grant.ApprovedType.ticket_travel,
         applicant_reply_deadline=datetime(2023, 2, 1, 23, 59, tzinfo=timezone.utc),
-        total_amount=680,
-        travel_amount=400,
         user=user,
     )
 
diff --git a/backend/integrations/tests/test_views.py b/backend/integrations/tests/test_views.py
index 5672bea6ee..0dcb2ef57c 100644
--- a/backend/integrations/tests/test_views.py
+++ b/backend/integrations/tests/test_views.py
@@ -145,8 +145,6 @@ def test_get_plain_customer_cards_grant_card(rest_api_client):
     user = UserFactory()
     grant = GrantFactory(
         user=user,
-        approved_type=Grant.ApprovedType.ticket_travel_accommodation,
-        travel_amount=100,
     )
     conference_id = grant.conference_id
     rest_api_client.token_auth("secret")
@@ -200,8 +198,6 @@ def test_get_plain_customer_cards_grant_card_with_no_travel(rest_api_client):
     user = UserFactory()
     grant = GrantFactory(
         user=user,
-        approved_type=Grant.ApprovedType.ticket_only,
-        travel_amount=100,
     )
     conference_id = grant.conference_id
     rest_api_client.token_auth("secret")
diff --git a/backend/reviews/admin.py b/backend/reviews/admin.py
index ebd21c5ea4..a0ff0be0a1 100644
--- a/backend/reviews/admin.py
+++ b/backend/reviews/admin.py
@@ -1,4 +1,5 @@
 from django.contrib.postgres.expressions import ArraySubquery
+from django.contrib.postgres.aggregates import ArrayAgg
 from django.db.models.expressions import ExpressionWrapper
 from django.db.models import FloatField
 from django.db.models.functions import Cast
@@ -17,7 +18,7 @@
 from django.urls import path, reverse
 from django.utils.safestring import mark_safe
 
-from grants.models import Grant
+from grants.models import Grant, AidCategory
 from participants.models import Participant
 from reviews.models import AvailableScoreOption, ReviewSession, UserReview
 from submissions.models import Submission, SubmissionTag
@@ -340,6 +341,9 @@ def _review_grants_recap_view(self, request, review_session):
                     )
                     .values("id")
                 ),
+                approved_aid_categories=ArrayAgg(
+                    "allocations__category_id",
+                ),
             )
             .order_by(F("score").desc(nulls_last=True))
             .prefetch_related(
@@ -376,8 +380,13 @@ def _review_grants_recap_view(self, request, review_session):
                 for choice in Grant.Status.choices
                 if choice[0] in Grant.REVIEW_SESSION_STATUSES_OPTIONS
             ],
+            all_approved_category=[
+                category
+                for category in AidCategory.objects.for_conference(
+                    conference=review_session.conference
+                )
+            ],
             all_statuses=Grant.Status.choices,
-            all_approved_types=[choice for choice in Grant.ApprovedType.choices],
             review_session=review_session,
             title="Recap",
         )
diff --git a/backend/reviews/templates/grants-recap.html b/backend/reviews/templates/grants-recap.html
index 71851bd534..7f26343415 100644
--- a/backend/reviews/templates/grants-recap.html
+++ b/backend/reviews/templates/grants-recap.html
@@ -22,20 +22,24 @@
     width: 150px;
   }
 
-  .approved-type-choices {
+  .approved-aid-categories-choices {
     width: 200px;
   }
 
   .status-choices,
-  .approved-type-choices {
+  .approved-aid-categories-choices {
     list-style: none;
   }
 
   .status-choices li,
-  .approved-type-choices li {
+  .approved-aid-categories-choices li {
     list-style: none;
   }
 
+  label:has(input.approved-aid-category:disabled) {
+      opacity: 0.6;
+  }
+
   .needs-list {
     display: inline-block;
     margin-top: 0;
@@ -289,18 +293,26 @@
               const grantRow = document.querySelector(`#grant-${grantId}`);
 
               const originalStatus = grantRow.dataset.originalStatus;
-              const originalApprovedType = grantRow.dataset.originalApprovedType;
-
+              const originalApprovedAidCategories = grantRow.dataset.originalApprovedAidCategories;
               grantRow.querySelector(`.status-decision-radio[value="${originalStatus}"]`).checked = true;
 
-              if (originalApprovedType !== 'None') {
-                  grantRow.querySelector(`.approved-type-choices input[value="${originalApprovedType}"]`).checked = true;
-              }
+              const checkboxes = grantRow.querySelectorAll(`.approved-aid-categories-choices input[type="checkbox"]`);
+              checkboxes.forEach(checkbox => {
+                checkbox.checked = false;
+
+                if (originalApprovedAidCategories.includes(checkbox.value)) {
+                    checkbox.checked = true;
+                }
+              });
 
               if (originalStatus === "approved") {
-                  grantRow.querySelector(`.approved-type-choices`).classList.remove('hidden');
+                  checkboxes.forEach(checkbox => {
+                      checkbox.disabled = false;
+                  });
               } else {
-                  grantRow.querySelector(`.approved-type-choices`).classList.add('hidden');
+                  checkboxes.forEach(checkbox => {
+                      checkbox.disabled = true;
+                  });
               }
           });
       });
@@ -308,13 +320,17 @@
       document.querySelectorAll('.status-decision-radio').forEach(radio => {
           radio.addEventListener('click', () => {
               const grantId = radio.name.split('-')[1];
-
-              const approvedTypeSection = document.querySelector(`.approved-type-choices[data-item-id="${grantId}"]`)
+              const approvedAidCategorySection = document.querySelector(`.approved-aid-categories-choices[data-item-id="${grantId}"]`);
+              const checkboxes = approvedAidCategorySection.querySelectorAll('input[type="checkbox"]');
 
               if (radio.value === "approved") {
-                  approvedTypeSection.classList.remove('hidden');
+                  checkboxes.forEach(checkbox => {
+                      checkbox.disabled = false;
+                  });
               } else {
-                  approvedTypeSection.classList.add('hidden');
+                  checkboxes.forEach(checkbox => {
+                      checkbox.disabled = true;
+                  });
               }
           });
       });
@@ -452,7 +468,7 @@ <h3>
                 </th>
                 <th scope="col">
                   <div class="text">
-                    <span>Approved type</span>
+                    <span>Approved Aids</span>
                   </div>
                   <div class="clear"></div>
                 </th>
@@ -470,7 +486,7 @@ <h3>
               </script>
               <tr
                 data-original-status="{{ item.status }}"
-                data-original-approved-type="{{ item.approved_type }}"
+                data-original-approved-aid-categories="{{ item.approved_aid_categories }}"
                 class="grant-item"
                 id="grant-{{ item.id }}"
                 data-type="{{ item.type }}"
@@ -623,24 +639,30 @@ <h3>
                 <td>
                   {% if perms.reviews.decision_reviewsession %}
                   <ul
-                    data-item-id="{{ item.id }}"
-                    class="approved-type-choices {% if item.status != 'approved' %}hidden{% endif %}"
+                  data-item-id="{{ item.id }}"
+                  class="approved-aid-categories-choices"
                   >
-                    {% for approved_type in all_approved_types %}
+                    {% for category in all_approved_category %}
                     <li>
                       <label>
-                        <input {% if item.approved_type == approved_type.0 %}checked{% endif %}
-                          type="radio" name="approvedtype-{{item.id}}" value="{{approved_type.0}}" />
-                        {{approved_type.1}}
+
+                          <input
+                              type="checkbox"
+                              name="approvedaidcategory-{{item.id}}"
+                              class="approved-aid-category"
+                              value="{{category.id}}"
+                              {% if item.status != 'approved' %}disabled{% endif %}
+                              {% if category.id in item.approved_aid_categories %}
+                                  checked
+                              {% elif not item.approved_aid_categories and item.status == 'approved' and category.included_by_default %}
+                              {% comment %} TODO FIX THIS IF {% endcomment %}
+                                  checked
+                              {% endif %}
+                          />
+                        {{category.name}}
                       </label>
                     </li>
                     {% endfor %}
-                    <li>
-                      <label>
-                        <input class="unset-radio" type="radio" name="approvedtype-{{item.id}}" value="unset" />
-                          Unset
-                      </label>
-                    </li>
                   </ul>
                   {% else %} No permission to change. {% endif %}
                 </td>