From 014e88aa24f9e1d2c40f8cf6129fd7a18d193d0e Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 17 Oct 2025 10:35:47 +0200 Subject: [PATCH 1/2] remove the help text about billing entity being read only The issue is that when obj.has_inherited_billing_entity is True, the code adds "billing_entity" to the readonly fields. When a field is marked as readonly, Django may exclude it from form.base_fields, which causes a KeyError when trying to access it. --- src/servala/core/admin.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/servala/core/admin.py b/src/servala/core/admin.py index 1aec22a..c0beb9e 100644 --- a/src/servala/core/admin.py +++ b/src/servala/core/admin.py @@ -73,16 +73,6 @@ class OrganizationAdmin(admin.ModelAdmin): return readonly_fields - def get_form(self, request, obj=None, **kwargs): - form = super().get_form(request, obj, **kwargs) - - if obj and obj.has_inherited_billing_entity: - form.base_fields["billing_entity"].help_text = _( - "This billing entity is inherited from the organization's origin and cannot be modified." - ) - - return form - @admin.register(BillingEntity) class BillingEntityAdmin(admin.ModelAdmin): From 54998ab9d0f6265297afb17ba6330380cc9eef26 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 17 Oct 2025 10:40:00 +0200 Subject: [PATCH 2/2] explicitely convert is_accepted to boolean The is_accepted property returns self.accepted_by or self.accepted_at. When accepted_by is a User object (not None), it returns the User object instead of a boolean. The Django admin's boolean field renderer expects a boolean value (True, False, or None), not a User object. --- src/servala/core/models/organization.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/servala/core/models/organization.py b/src/servala/core/models/organization.py index d308bfa..1669f39 100644 --- a/src/servala/core/models/organization.py +++ b/src/servala/core/models/organization.py @@ -485,7 +485,7 @@ class OrganizationInvitation(ServalaModelMixin, models.Model): def is_accepted(self): # We check both accepted_by and accepted_at to avoid a deleted user # freeing up an invitation - return self.accepted_by or self.accepted_at + return bool(self.accepted_by or self.accepted_at) @property def can_be_accepted(self):