Files
bakery-ia/services/tenant/app/repositories/tenant_location_repository.py
2025-11-30 09:12:40 +01:00

218 lines
8.0 KiB
Python

"""
Tenant Location Repository
Handles database operations for tenant location data
"""
from typing import List, Optional, Dict, Any
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, update, delete
from sqlalchemy.orm import selectinload
import structlog
from app.models.tenant_location import TenantLocation
from app.models.tenants import Tenant
from shared.database.exceptions import DatabaseError
from .base import BaseRepository
logger = structlog.get_logger()
class TenantLocationRepository(BaseRepository):
"""Repository for tenant location operations"""
def __init__(self, session: AsyncSession):
super().__init__(TenantLocation, session)
async def create_location(self, location_data: Dict[str, Any]) -> TenantLocation:
"""
Create a new tenant location
Args:
location_data: Dictionary containing location information
Returns:
Created TenantLocation object
"""
try:
# Create new location instance
location = TenantLocation(**location_data)
self.session.add(location)
await self.session.commit()
await self.session.refresh(location)
logger.info(f"Created new tenant location: {location.id} for tenant {location.tenant_id}")
return location
except Exception as e:
await self.session.rollback()
logger.error(f"Failed to create tenant location: {str(e)}")
raise DatabaseError(f"Failed to create tenant location: {str(e)}")
async def get_location_by_id(self, location_id: str) -> Optional[TenantLocation]:
"""
Get a location by its ID
Args:
location_id: UUID of the location
Returns:
TenantLocation object if found, None otherwise
"""
try:
stmt = select(TenantLocation).where(TenantLocation.id == location_id)
result = await self.session.execute(stmt)
location = result.scalar_one_or_none()
return location
except Exception as e:
logger.error(f"Failed to get location by ID: {str(e)}")
raise DatabaseError(f"Failed to get location by ID: {str(e)}")
async def get_locations_by_tenant(self, tenant_id: str) -> List[TenantLocation]:
"""
Get all locations for a specific tenant
Args:
tenant_id: UUID of the tenant
Returns:
List of TenantLocation objects
"""
try:
stmt = select(TenantLocation).where(TenantLocation.tenant_id == tenant_id)
result = await self.session.execute(stmt)
locations = result.scalars().all()
return locations
except Exception as e:
logger.error(f"Failed to get locations by tenant: {str(e)}")
raise DatabaseError(f"Failed to get locations by tenant: {str(e)}")
async def get_location_by_type(self, tenant_id: str, location_type: str) -> Optional[TenantLocation]:
"""
Get a location by tenant and type
Args:
tenant_id: UUID of the tenant
location_type: Type of location (e.g., 'central_production', 'retail_outlet')
Returns:
TenantLocation object if found, None otherwise
"""
try:
stmt = select(TenantLocation).where(
TenantLocation.tenant_id == tenant_id,
TenantLocation.location_type == location_type
)
result = await self.session.execute(stmt)
location = result.scalar_one_or_none()
return location
except Exception as e:
logger.error(f"Failed to get location by type: {str(e)}")
raise DatabaseError(f"Failed to get location by type: {str(e)}")
async def update_location(self, location_id: str, location_data: Dict[str, Any]) -> Optional[TenantLocation]:
"""
Update a tenant location
Args:
location_id: UUID of the location to update
location_data: Dictionary containing updated location information
Returns:
Updated TenantLocation object if successful, None if location not found
"""
try:
stmt = (
update(TenantLocation)
.where(TenantLocation.id == location_id)
.values(**location_data)
)
await self.session.execute(stmt)
# Now fetch the updated location
location_stmt = select(TenantLocation).where(TenantLocation.id == location_id)
result = await self.session.execute(location_stmt)
location = result.scalar_one_or_none()
if location:
await self.session.commit()
logger.info(f"Updated tenant location: {location_id}")
return location
else:
await self.session.rollback()
logger.warning(f"Location not found for update: {location_id}")
return None
except Exception as e:
await self.session.rollback()
logger.error(f"Failed to update location: {str(e)}")
raise DatabaseError(f"Failed to update location: {str(e)}")
async def delete_location(self, location_id: str) -> bool:
"""
Delete a tenant location
Args:
location_id: UUID of the location to delete
Returns:
True if deleted successfully, False if location not found
"""
try:
stmt = delete(TenantLocation).where(TenantLocation.id == location_id)
result = await self.session.execute(stmt)
if result.rowcount > 0:
await self.session.commit()
logger.info(f"Deleted tenant location: {location_id}")
return True
else:
await self.session.rollback()
logger.warning(f"Location not found for deletion: {location_id}")
return False
except Exception as e:
await self.session.rollback()
logger.error(f"Failed to delete location: {str(e)}")
raise DatabaseError(f"Failed to delete location: {str(e)}")
async def get_active_locations_by_tenant(self, tenant_id: str) -> List[TenantLocation]:
"""
Get all active locations for a specific tenant
Args:
tenant_id: UUID of the tenant
Returns:
List of active TenantLocation objects
"""
try:
stmt = select(TenantLocation).where(
TenantLocation.tenant_id == tenant_id,
TenantLocation.is_active == True
)
result = await self.session.execute(stmt)
locations = result.scalars().all()
return locations
except Exception as e:
logger.error(f"Failed to get active locations by tenant: {str(e)}")
raise DatabaseError(f"Failed to get active locations by tenant: {str(e)}")
async def get_locations_by_tenant_with_type(self, tenant_id: str, location_types: List[str]) -> List[TenantLocation]:
"""
Get locations for a specific tenant filtered by location types
Args:
tenant_id: UUID of the tenant
location_types: List of location types to filter by
Returns:
List of TenantLocation objects matching the criteria
"""
try:
stmt = select(TenantLocation).where(
TenantLocation.tenant_id == tenant_id,
TenantLocation.location_type.in_(location_types)
)
result = await self.session.execute(stmt)
locations = result.scalars().all()
return locations
except Exception as e:
logger.error(f"Failed to get locations by tenant and type: {str(e)}")
raise DatabaseError(f"Failed to get locations by tenant and type: {str(e)}")