Source code for ferrosoft.apps.ferrobase.views.tenant
# Copyright (c) 2025 Ferrosoft GmbH. All rights reserved.
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from django.urls import reverse
from ferrosoft.apps.ferrobase.forms import TenantForm
from ferrosoft.apps.ferrobase.middleware import TenantMiddleware
from ferrosoft.apps.ferrobase.models import Tenant, Organization
from ferrosoft.apps.ferrobase.views.generic import (
UpdateView,
DeleteView,
model_crud_routes,
DependentCreateView,
)
def _tenant_options(request):
"""Build the ``(label, url)`` tenant-selection options for the current user.
Superusers see every tenant; regular users see only the tenants attached
to their organisation. Each generated URL preserves the post-selection
redirect target via ``?next=…``.
"""
go_to_url = request.GET.get("next", None)
if go_to_url is None:
go_to_url = reverse("ferrobase:index")
tenants = (
Tenant.all_ordered()
if request.user.is_superuser
else request.user.organization.tenants.order_by("name")
)
return [
(
str(tenant),
"%s?%s=%s"
% (
go_to_url,
TenantMiddleware.TENANT_REQUEST_KEY,
str(tenant.pk),
),
)
for tenant in tenants
]
[docs]
@login_required
def choose_tenant(request):
"""Tenant-selection page; auto-redirects when the user has a single tenant."""
options = _tenant_options(request)
if len(options) == 1:
return redirect(options[0][1])
return render(
request,
"ferrobase/tenant-list.html",
context={
"tenant_options": options,
},
)
[docs]
class TenantCreateView(DependentCreateView):
"""Create a tenant scoped to an :class:`Organization` (the dependent parent)."""
form_class = TenantForm
model = Tenant
parent_model = Organization
template_name = "ferrobase/tenant/create.html"
[docs]
def cancel_view(self):
"""Return to the parent organisation, or hide the cancel button."""
return (
None
if self.parent_object is None
else reverse("ferrobase:organization_update", args=[self.parent_object.pk])
)
[docs]
class TenantUpdateView(UpdateView):
"""Update a tenant; navigation always returns to the parent organisation."""
form_class = TenantForm
model = Tenant
related_links_default = False
[docs]
def cancel_view(self):
"""Cancel returns to the owning organisation's update page."""
return reverse(
"ferrobase:organization_update", args=[self.object.organization.pk]
)
[docs]
def get_success_url(self):
"""Success also returns to the owning organisation's update page."""
return reverse(
"ferrobase:organization_update", args=[self.object.organization.pk]
)
[docs]
class TenantDeleteView(DeleteView):
"""Delete a tenant; redirects back to the owning organisation."""
model = Tenant
[docs]
def get_success_url(self):
"""Return to the owning organisation's update page after deletion."""
return reverse(
"ferrobase:organization_update", args=[self.object.organization.pk]
)
tenant_urls = model_crud_routes(
Tenant,
create_view=TenantCreateView,
update_view=TenantUpdateView,
delete_view=TenantDeleteView,
)