"""Business logic for planned leave days (calendar planning).""" from datetime import date, datetime from uuid import UUID, uuid4 from app.entities.planned_leave import PlannedLeaveDay from app.repositories.planned_leave_repository import PlannedLeaveRepository from app.services.analytics_service import AnalyticsService from app.utils.errors import NotFoundError, ValidationError class PlanningService: def __init__( self, repo: PlannedLeaveRepository, analytics_service: AnalyticsService, ) -> None: self._repo = repo self._analytics = analytics_service async def add_planned_day( self, workspace_id: UUID, child_id: UUID, parent_personal_data_uuid: UUID, date: date, day_type: str, is_dubbeldag: bool = False, ) -> PlannedLeaveDay: """Add a planned leave day. Validates that the day is available (dubbeldagar rules, no double-booking). """ # Validation 1: Check dubbeldagar quota if this is a dubbeldag if is_dubbeldag: await self._analytics.validate_dubbeldagar(child_id, date) # Validation 2: Check no double-booking on the same date existing = await self._repo.list_by_workspace_child( workspace_id=workspace_id, child_id=child_id, from_date=date, to_date=date, ) if existing: raise ValidationError(f"A planned day already exists on {date}") now = datetime.now() entity = PlannedLeaveDay( id=uuid4(), workspace_id=workspace_id, child_id=child_id, parent_personal_data_uuid=parent_personal_data_uuid, date=date, day_type=day_type, is_dubbeldag=is_dubbeldag, created_at=now, updated_at=now, ) return await self._repo.create(entity) async def remove_planned_day(self, planned_leave_day_id: UUID) -> None: """Remove a planned leave day.""" entity = await self._repo.get_by_id(planned_leave_day_id) if entity is None: raise NotFoundError(f"PlannedLeaveDay {planned_leave_day_id} not found") await self._repo.delete(planned_leave_day_id) async def list_by_workspace(self, workspace_id: UUID) -> list[PlannedLeaveDay]: """Get all planned days for a workspace.""" return await self._repo.list(workspace_id=workspace_id) async def list_by_date_range( self, workspace_id: UUID, child_id: UUID, start_date: date, end_date: date, ) -> list[PlannedLeaveDay]: """Get planned days within a date range for a child.""" return await self._repo.list_by_workspace_child( workspace_id=workspace_id, child_id=child_id, from_date=start_date, to_date=end_date, ) async def get(self, planned_leave_day_id: UUID) -> PlannedLeaveDay: """Get a planned day by ID.""" entity = await self._repo.get_by_id(planned_leave_day_id) if entity is None: raise NotFoundError(f"PlannedLeaveDay {planned_leave_day_id} not found") return entity