feat: add multi-tenant system with properties, organizations, and public booking

Implement complete multi-property architecture:
- Properties (groups of spaces) with public/private visibility
- Property managers (many-to-many) with role-based permissions
- Organizations with member management
- Anonymous/guest booking support via public API (/api/public/*)
- Property-scoped spaces, bookings, and settings
- Frontend: property selector, organization management, public booking views
- Migration script and updated seed data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-02-15 00:17:21 +00:00
parent d637513d92
commit e21cf03a16
51 changed files with 6324 additions and 273 deletions

View File

@@ -0,0 +1,82 @@
"""Property schemas."""
from datetime import datetime
from pydantic import BaseModel, Field
class PropertyCreate(BaseModel):
name: str = Field(..., min_length=1)
description: str | None = None
address: str | None = None
is_public: bool = True
class PropertyUpdate(BaseModel):
name: str | None = None
description: str | None = None
address: str | None = None
is_public: bool | None = None
class PropertyManagerInfo(BaseModel):
user_id: int
full_name: str
email: str
class PropertyResponse(BaseModel):
id: int
name: str
description: str | None = None
address: str | None = None
is_public: bool
is_active: bool
created_at: datetime
space_count: int = 0
managers: list[PropertyManagerInfo] = []
model_config = {"from_attributes": True}
class PropertyWithSpaces(PropertyResponse):
spaces: list = []
class PropertyAccessCreate(BaseModel):
user_id: int | None = None
organization_id: int | None = None
class PropertyAccessResponse(BaseModel):
id: int
property_id: int
user_id: int | None = None
organization_id: int | None = None
granted_by: int | None = None
user_name: str | None = None
user_email: str | None = None
organization_name: str | None = None
created_at: datetime
model_config = {"from_attributes": True}
class PropertySettingsUpdate(BaseModel):
working_hours_start: int | None = None
working_hours_end: int | None = None
min_duration_minutes: int | None = None
max_duration_minutes: int | None = None
max_bookings_per_day_per_user: int | None = None
require_approval: bool = True
min_hours_before_cancel: int | None = None
class PropertySettingsResponse(PropertySettingsUpdate):
id: int
property_id: int
model_config = {"from_attributes": True}
class PropertyStatusUpdate(BaseModel):
is_active: bool