TorbatYar/backend/services/hospitality/app/repositories/foundation.py
Mortezakoohjani 5c6a2e78cf feat(platform): seed service registry, deploy all modules, and fix homepage catalog.
Register all active platform services and base features in core DB so admin can manage them, add delivery/hospitality/sports-center backend phases, update apps catalog and production deploy tooling.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 12:39:51 +03:30

304 lines
10 KiB
Python

"""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()