Files

44 lines
1.3 KiB
Python

"""
app/tenancy/context.py
----------------------
Lightweight, detached descriptor for the resolved tenant. Populated by the
resolver while a control-plane session is open, then carried on `g.tenant`
for the lifetime of the request. Holds no live ORM object — safe to use after
the control session closes.
MT-5: plan feature flags and quota limits are included so quota.py and
gates.py can read them from g.tenant without a second control-DB round-trip.
"""
from dataclasses import dataclass
from datetime import datetime
from typing import Optional
@dataclass(frozen=True)
class TenantContext:
id: int
slug: str
name: str
plan_id: int
db_uri: str
# MT-5: plan fields (None = unlimited / not loaded)
plan_code: Optional[str] = None
# Quota limits (None = unlimited)
max_users: Optional[int] = None
max_facilities: Optional[int] = None
max_inspections_month: Optional[int] = None
max_issues_month: Optional[int] = None
# Feature gates
allow_mobile_api: bool = True
allow_scheduled_reports: bool = True
allow_branding: bool = True
allow_custom_domain: bool = True
# MT-8: billing state (None = billing not configured / legacy tenant)
subscription_status: Optional[str] = None # trial|active|past_due|cancelled
trial_ends_at: Optional[datetime] = None