"""Hospitality foundation repositories — Phase 12.0.""" from __future__ import annotations from uuid import UUID from sqlalchemy import select from app.models.foundation import ( Branch, BundleDefinition, DiningArea, DiningTable, FeatureToggle, HospitalityAuditLog, HospitalityConfiguration, HospitalityEvent, HospitalityPermission, HospitalityRole, HospitalitySetting, Menu, MenuCategory, MenuItem, TenantBundle, Venue, ) from app.models.types import BundleKey, BundleStatus from app.repositories.base import TenantBaseRepository class VenueRepository(TenantBaseRepository[Venue]): model = Venue async def get_by_code(self, tenant_id: UUID, code: str) -> Venue | None: stmt = select(Venue).where( Venue.tenant_id == tenant_id, Venue.code == code, Venue.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() class BranchRepository(TenantBaseRepository[Branch]): model = Branch async def get_by_code( self, tenant_id: UUID, venue_id: UUID, code: str ) -> Branch | None: stmt = select(Branch).where( Branch.tenant_id == tenant_id, Branch.venue_id == venue_id, Branch.code == code, Branch.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() class DiningAreaRepository(TenantBaseRepository[DiningArea]): model = DiningArea async def get_by_code( self, tenant_id: UUID, venue_id: UUID, code: str ) -> DiningArea | None: stmt = select(DiningArea).where( DiningArea.tenant_id == tenant_id, DiningArea.venue_id == venue_id, DiningArea.code == code, DiningArea.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() class DiningTableRepository(TenantBaseRepository[DiningTable]): model = DiningTable async def get_by_code( self, tenant_id: UUID, venue_id: UUID, code: str ) -> DiningTable | None: stmt = select(DiningTable).where( DiningTable.tenant_id == tenant_id, DiningTable.venue_id == venue_id, DiningTable.code == code, DiningTable.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() class MenuRepository(TenantBaseRepository[Menu]): model = Menu async def get_by_code( self, tenant_id: UUID, venue_id: UUID, code: str ) -> Menu | None: stmt = select(Menu).where( Menu.tenant_id == tenant_id, Menu.venue_id == venue_id, Menu.code == code, Menu.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() class MenuCategoryRepository(TenantBaseRepository[MenuCategory]): model = MenuCategory async def get_by_code( self, tenant_id: UUID, menu_id: UUID, code: str ) -> MenuCategory | None: stmt = select(MenuCategory).where( MenuCategory.tenant_id == tenant_id, MenuCategory.menu_id == menu_id, MenuCategory.code == code, MenuCategory.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() class MenuItemRepository(TenantBaseRepository[MenuItem]): model = MenuItem async def get_by_code( self, tenant_id: UUID, menu_id: UUID, code: str ) -> MenuItem | None: stmt = select(MenuItem).where( MenuItem.tenant_id == tenant_id, MenuItem.menu_id == menu_id, MenuItem.code == code, MenuItem.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() class BundleDefinitionRepository(TenantBaseRepository[BundleDefinition]): model = BundleDefinition async def get_by_key( self, tenant_id: UUID, bundle_key: BundleKey ) -> BundleDefinition | None: stmt = select(BundleDefinition).where( BundleDefinition.tenant_id == tenant_id, BundleDefinition.bundle_key == bundle_key, BundleDefinition.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() async def get_by_code(self, tenant_id: UUID, code: str) -> BundleDefinition | None: stmt = select(BundleDefinition).where( BundleDefinition.tenant_id == tenant_id, BundleDefinition.code == code, BundleDefinition.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() class TenantBundleRepository(TenantBaseRepository[TenantBundle]): model = TenantBundle async def get_active( self, tenant_id: UUID, bundle_key: BundleKey, venue_id: UUID | None = None ) -> TenantBundle | None: stmt = select(TenantBundle).where( TenantBundle.tenant_id == tenant_id, TenantBundle.bundle_key == bundle_key, TenantBundle.venue_id == venue_id, TenantBundle.status == BundleStatus.ACTIVE, TenantBundle.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() async def list_active(self, tenant_id: UUID, venue_id: UUID | None = None): clauses = [ TenantBundle.tenant_id == tenant_id, TenantBundle.status == BundleStatus.ACTIVE, TenantBundle.is_deleted.is_(False), ] if venue_id is None: clauses.append(TenantBundle.venue_id.is_(None)) else: clauses.append(TenantBundle.venue_id == venue_id) stmt = select(TenantBundle).where(*clauses) result = await self.session.execute(stmt) return result.scalars().all() class FeatureToggleRepository(TenantBaseRepository[FeatureToggle]): model = FeatureToggle async def get_by_key( self, tenant_id: UUID, feature_key: str, venue_id: UUID | None = None ) -> FeatureToggle | None: stmt = select(FeatureToggle).where( FeatureToggle.tenant_id == tenant_id, FeatureToggle.feature_key == feature_key, FeatureToggle.venue_id == venue_id, FeatureToggle.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() async def list_enabled(self, tenant_id: UUID, venue_id: UUID | None = None): clauses = [ FeatureToggle.tenant_id == tenant_id, FeatureToggle.enabled.is_(True), FeatureToggle.is_deleted.is_(False), ] if venue_id is None: clauses.append(FeatureToggle.venue_id.is_(None)) else: clauses.append(FeatureToggle.venue_id == venue_id) stmt = select(FeatureToggle).where(*clauses) result = await self.session.execute(stmt) return result.scalars().all() class HospitalityRoleRepository(TenantBaseRepository[HospitalityRole]): model = HospitalityRole async def get_by_code(self, tenant_id: UUID, code: str) -> HospitalityRole | None: stmt = select(HospitalityRole).where( HospitalityRole.tenant_id == tenant_id, HospitalityRole.code == code, HospitalityRole.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() class HospitalityPermissionRepository(TenantBaseRepository[HospitalityPermission]): model = HospitalityPermission async def get_by_code( self, tenant_id: UUID, code: str ) -> HospitalityPermission | None: stmt = select(HospitalityPermission).where( HospitalityPermission.tenant_id == tenant_id, HospitalityPermission.code == code, HospitalityPermission.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() class HospitalityConfigurationRepository(TenantBaseRepository[HospitalityConfiguration]): model = HospitalityConfiguration async def get_by_code( self, tenant_id: UUID, code: str ) -> HospitalityConfiguration | None: stmt = select(HospitalityConfiguration).where( HospitalityConfiguration.tenant_id == tenant_id, HospitalityConfiguration.code == code, HospitalityConfiguration.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() class HospitalityEventRepository(TenantBaseRepository[HospitalityEvent]): model = HospitalityEvent class HospitalitySettingRepository(TenantBaseRepository[HospitalitySetting]): model = HospitalitySetting async def get_by_key( self, tenant_id: UUID, key: str, venue_id: UUID | None = None ) -> HospitalitySetting | None: stmt = select(HospitalitySetting).where( HospitalitySetting.tenant_id == tenant_id, HospitalitySetting.key == key, HospitalitySetting.venue_id == venue_id, HospitalitySetting.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() class HospitalityAuditLogRepository(TenantBaseRepository[HospitalityAuditLog]): model = HospitalityAuditLog async def list_for_entity( self, tenant_id: UUID, entity_type: str, entity_id: UUID, *, limit: int = 100 ): stmt = ( select(HospitalityAuditLog) .where( HospitalityAuditLog.tenant_id == tenant_id, HospitalityAuditLog.entity_type == entity_type, HospitalityAuditLog.entity_id == entity_id, ) .limit(limit) ) result = await self.session.execute(stmt) return result.scalars().all()