"""Space queries scoped by tenant membership.""" from __future__ import annotations from django.db.models import Q, QuerySet from coulomb_social.apps.members.models import Member from .models import Space, SpaceMembership def spaces_for_member(member: Member | None) -> QuerySet[Space]: """Spaces visible to this member (same tenant, active). Explicit SpaceMembership grants access; if none exist for the tenant yet, all active tenant spaces are listed (operator-seeded MVP). Once any memberships exist for the tenant, only membership + created_by apply. """ if member is None: return Space.objects.none() qs = Space.objects.filter(tenant_id=member.tenant_id, is_active=True) tenant_has_memberships = SpaceMembership.objects.filter( space__tenant_id=member.tenant_id ).exists() if not tenant_has_memberships: return qs.order_by("title", "slug") return ( qs.filter(Q(memberships__member=member) | Q(created_by=member)) .distinct() .order_by("title", "slug") ) def get_space_for_member(member: Member | None, slug: str) -> Space | None: if member is None: return None return spaces_for_member(member).filter(slug=slug).first()